Reputation: 588
Considering the following DOM distribution. I have a flexbox
container with two children, one of them has a fixed size while the other shrinks with an overflow: hidden
. I was wondering, however, if there is a way for the overflown content to remain visible without any impact on the flow of the DOM.
Fleshed out Example at Codepen
ul.current {
list-style: none;
display: flex;
width: 40%;
margin: 0 auto;
}
li {
overflow: hidden;
}
li:last-child {
flex-shrink: 0;
}
li div {
border: 1px solid black;
background: green;
width: 10rem;
height: 10rem;
}
li:last-child {
margin-top: 2rem;
}
li:last-child div {
background: red;
}
/* GOAL */
section {
margin: 0 auto;
width: 40%;
}
.item {
position: absolute;
}
.item:last-child {
margin-top: 2rem;
margin-left: 5rem;
}
.content {
border: 1px solid black;
background: green;
width: 10rem;
height: 10rem;
}
.item:last-child .content {
background: red;
}
<h3>Shrink the viewport to get an idea of what's the intended scenario</h3>
<ul class="current">
<li><div></div></li>
<li><div></div></li>
</ul>
<h3>Visual representation of the overlap behavior</h3>
<section>
<div class="item"><div class="content"></div></div>
<div class="item"><div class="content"></div></div>
</section>
What I want, basically, is for the images to "overlap" each other in a flexible context, meaning, a solution that would work on N cases.
Upvotes: 2
Views: 2318
Reputation: 272592
In order to have an overlap you have to either use positioned elements (which is not the best solution if you want to keep the element in-flow) or use negative margin.
Let's consider negative margin. The trick is to find a way to adjust the margin in order to create the overlap when the parent container will shrink.
Here is a basic example:
section {
max-width: 300px;
border: 1px solid;
animation:change 2s linear infinite alternate;
}
@keyframes change {
from {max-width: 300px;}
to {max-width: 100px;}
}
.item{
height: 80px;
min-width: 80px;
background:blue;
display: inline-block;
vertical-align:top;
margin-right:calc((100% - 200px)/2);
}
.item:last-child {
margin-top: 2rem;
background: red;
}
<section>
<div class="item">
</div>
<div class="item">
</div>
</section>
As you can see, the trick is to define the margin considering the width of the container (100%) and we will have two cases:
Xpx
we have a positive margin and a normal behavior with spacingXpx
we will have a negative margin and will have the overlap effect without wrapping.We need to simply find the good way to define the margin in order to obtain the needed behavior. We may also consider media query in case we want a different behavior like having no margin and then overlapping:
section {
border: 1px solid;
font-size:0;
}
.item{
height: 80px;
min-width: 80px;
background:blue;
display: inline-block;
vertical-align:top;
}
.item:nth-child(odd) {
margin-top: 2rem;
background: red;
}
@media all and (max-width:350px) {
.item{
margin-right:calc((100% - 320px)/4)
}
}
<section>
<div class="item">
</div>
<div class="item">
</div>
<div class="item">
</div>
<div class="item">
</div>
</section>
Another idea that work with nested element (like your intial code) is to keep the overflow visible and force the outer element to shrink using min-width:0
.
ul.current {
list-style: none;
display: flex;
width: 40%;
margin: 0 auto;
animation:change 2s infinite linear alternate;
}
@keyframes change {
from {width:100%}
to {width:40%}
}
li {
min-width:0;
}
li div {
border: 1px solid black;
background: green;
width: 10rem;
height: 10rem;
}
li:nth-child(odd) {
margin-top: 2rem;
}
li:nth-child(odd) div {
background: red;
}
/* GOAL */
section {
margin: 0 auto;
width: 40%;
}
.item {
position: absolute;
}
.item:last-child {
margin-top: 2rem;
margin-left: 5rem;
}
.content {
border: 1px solid black;
background: green;
width: 10rem;
height: 10rem;
}
.item:last-child .content {
background: red;
}
<ul class="current">
<li><div></div></li>
<li><div></div></li>
<li><div></div></li>
<li><div></div></li>
</ul>
Upvotes: 1
Reputation: 28553
Your issue may be more clear to resolve if you didn't use quite as much inline style. I added classes and css to your code to make it easier to read.
By adding flex-wrap:wrap;
to the display:flex;
on the section, the images wrap. I set the images to background-images, and the bg-size to cover. If you wish the first-listed image to display second, simply switch the divs.
Hope this helps
#imagedisp {
display: flex;
flex-wrap: wrap;
}
#div1 {
flex-shrink: 1;
/* overflow: hidden;*/
border: 1px dashed;
background-image: url("https://s3-media4.fl.yelpcdn.com/bphoto/xFlymSQW0weBqXjwZM6Y2Q/ls.jpg");
}
#div2 {
margin-bottom: 40px;
border: 1px dashed;
background-image: url("https://s3-media3.fl.yelpcdn.com/bphoto/_-U30Zk2XbUKe2fcdtEXLQ/o.jpg");
}
#div1,
#div2 {
background-repeat: no-repeat;
background-position: center center;
background-size: cover;
}
div {
min-width: 300px;
/*width:300px;*/
height: 100px;
}
<section id="imagedisp">
<div id="div1">
<!-- <img />-->
</div>
<div id="div2">
<!-- <img />-->
</div>
</section>
Upvotes: 2