2

I'm struggling to get a flexbox layout working with margins and overflow: hidden.

The carousel component I'm integrating uses this method to be responsive but as soon as a display:flex is applied to the parent, the margin and overflow: hidden properties are ignored as shown in the example below.

The top version is not nested in a flexbox where as the one below it is, and is not respecting the margins of the parent.

flexbox issue with margins

The issue is demonstrated in the code below and in this Plunker. http://plnkr.co/edit/qU1oq1Vq1X3FQMWLJiQk?p=preview

body {
  margin: 400px;
}

.overflowHidden {
  overflow: hidden;
}

.flex {
  display: flex;
}
<div>
  <div class="overflowHidden">
    <img src="http://lorempixel.com/600/400" />
  </div>
</div>

<div class="flex">
  <div>
    <div class="overflowHidden">
      <img src="http://lorempixel.com/600/400" />
    </div>
  </div>
</div>

I know there are many similar questions on this topic but I couldn't find anything relating to my particular use case.

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
CountZero
  • 6,171
  • 3
  • 46
  • 59

2 Answers2

3

Here's the solution:

.flex > div { overflow: hidden }

revised demo


The first thing to note is that margins have nothing to do with this problem. Margins are, in fact, being respected. They are simply travelling with the element, which is expanding a container.


The non-flex div containers have display: block by default.

In a block formatting context, when an image becomes too big to fit in a container with overflow: hidden, it simply disappears, as expected.

The parent divs and their margins remain stable and undisturbed.

However, in a flex formatting context the behavior is different.

First, you have three levels of divs in the flex example. You only have two in the block example. But that's not really important.

The key piece of information here is this:

When you apply display: flex or display: inline-flex to an element it becomes a flex container and its children become flex items. By default, flex items cannot be smaller than the size of their content. They have a default setting of min-width: auto.

So, when an image becomes too big for its parent, the parent (if it's a flex item) must expand. But in your example, the parent of the image (div.overflowHidden) is not a flex item, it's a standard block element. So overflow: hidden is working fine (just like in the block example).

But the parent of the parent is a flex item. And its default setting is min-width: auto. And it cannot shrink below the size of its content (the image). So while the block example can remain on the screen at all times, the flex version will overflow the body / viewport, taking the right margin with it.

The solution is to override the min-width: auto default on the flex item. You can use:

  • min-width: 0

OR

  • overflow: hidden

More details here: Why doesn't flex item shrink past content size?

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
0

Not sure why that's happening exactly, but seems to work if you apply .overflowHidden to either an element that wraps the flex parent, or just apply it to the flex parent instead.

body {
  margin: 400px;
  overflow-x: hidden;
}

.overflowHidden {
  overflow: hidden;
}

.flex {
  display: flex;
  z-index: -1;
  position: relative;
}
<div>
  <div class="overflowHidden">
    <img src="http://lorempixel.com/600/400" />
  </div>
</div>
<div class="flex overflowHidden">
  <div>
    <img src="http://lorempixel.com/600/400" />
  </div>
</div>
<div class="overflowHidden">
  <div class="flex">
    <img src="http://lorempixel.com/600/400" />
  </div>
</div>
Michael Coker
  • 52,626
  • 5
  • 64
  • 64