1

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.

Temani Afif
  • 245,468
  • 26
  • 309
  • 415
Marco Toniut
  • 568
  • 1
  • 7
  • 16
  • Set the container to flex-wrap. Then use percentages like like 40% width and 60% width. Than on the image you want to pop down. Set a min-width in pixels. When it reaches that point it will pop down under. – KYSSE Dec 12 '18 at 23:58
  • My aim is for it not to wrap, but instead let the first elements shrink. `overflow: hidden` does achieve what I'm looking for, as per the example; however I was wondering if there was some other trick that would trigger the shrinking, while still rendering the overflown content. – Marco Toniut Dec 13 '18 at 02:43

2 Answers2

2

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>
Rachel Gallen
  • 27,943
  • 21
  • 72
  • 81
1

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:

  1. When the width is bigger than Xpx we have a positive margin and a normal behavior with spacing
  2. When the width is smaller than Xpx 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>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
  • Absolutely brilliant! Your second proposal is precisely what I was looking for. Would you care to expand a bit on why `min-width` behaves the way it does for this scenario? – Marco Toniut Dec 15 '18 at 17:00
  • 1
    @MarcoToniut you can check this for the min-width feature : https://stackoverflow.com/questions/36247140/why-dont-flex-items-shrink-past-content-size .. it's something related to flexbox, as you can see I didn't use it in the first examples – Temani Afif Dec 15 '18 at 19:03
  • Excellent. Thanks @Temani-Afif. It seems like I must wait for another 5 hours before I can award the bounty. – Marco Toniut Dec 15 '18 at 22:17
  • @MarcoToniut no hurry, you still have 5 days ;) you will probably get more intresting ways even if I don't think there will be ... but we never know ;) – Temani Afif Dec 16 '18 at 01:20