bygrace
bygrace

Reputation: 5988

Why is content overflowing in flexbox?

I am experiencing some behavior that I don't understand. When I set up a list of badges with a max-height on the list and margin on the list items then the content for the list items overflows their containers proportionally to the margin.

.badgers {
  display: flex;
  flex-direction: column;
  max-height: 10em;
  overflow: auto;
  border: 1px dashed red;
}

.badge, .title, .location, .timestamp {
  display: flex;
}

.badge {
  flex-direction: column;
  border: 1px solid black;
  margin: 1em 0;
}
<div class="badgers">
  <div class="badge">
      <span class="title">Title</span>
      <span class="location">Location</span>
      <span class="timestamp">Timestamp</span>
  </div>
  <div class="badge">
      <span class="title">Title 2</span>
      <span class="location">Location</span>
      <span class="timestamp">Timestamp</span>
  </div>
  <div class="badge">
      <span class="title">Title 3</span>
      <span class="location">Location</span>
      <span class="timestamp">Timestamp</span>
  </div>
</div>
  

If I remove the margin then there is no overflow.

.badgers {
  display: flex;
  flex-direction: column;
  max-height: 10em;
  overflow: auto;
  border: 1px dashed red;
}

.badge, .title, .location, .timestamp {
  display: flex;
}

.badge {
  flex-direction: column;
  border: 1px solid black;
}
<div class="badgers">
  <div class="badge">
      <span class="title">Title</span>
      <span class="location">Location</span>
      <span class="timestamp">Timestamp</span>
  </div>
  <div class="badge">
      <span class="title">Title 2</span>
      <span class="location">Location</span>
      <span class="timestamp">Timestamp</span>
  </div>
  <div class="badge">
      <span class="title">Title 3</span>
      <span class="location">Location</span>
      <span class="timestamp">Timestamp</span>
  </div>
</div>
  

If I change the wrapper to display: block and leave the margin then the list looks like what I want.

.badgers {
  max-height: 10em;
  overflow: auto;
  border: 1px dashed red;
}

.badge, .title, .location, .timestamp {
  display: flex;
}

.badge {
  flex-direction: column;
  border: 1px solid black;
  margin: 1em 0;
}
<div class="badgers">
  <div class="badge">
      <span class="title">Title</span>
      <span class="location">Location</span>
      <span class="timestamp">Timestamp</span>
  </div>
  <div class="badge">
      <span class="title">Title 2</span>
      <span class="location">Location</span>
      <span class="timestamp">Timestamp</span>
  </div>
  <div class="badge">
      <span class="title">Title 3</span>
      <span class="location">Location</span>
      <span class="timestamp">Timestamp</span>
  </div>
</div>
  

So why does the content overflow when the list is display: flex; flex-direction: column but not when it is display: block?

Upvotes: 3

Views: 3632

Answers (1)

Michael Benjamin
Michael Benjamin

Reputation: 372194

By default, flex items are set to flex-shrink: 1 (source).

This means they can shrink to avoid overflowing the container.

Disable this feature. Make your flex items flex-shrink: 0.


UPDATE (based on comments):

  • It doesn't work in Firefox.

    Actually, the solution above was tested in Chrome, Firefox and Edge. It works (fiddle demo).

  • It still works in Firefox when flex-shrink: 0 is removed.

    This is because in Firefox another default setting is in play: min-height: auto. This means that flex items can't shrink below the height of their content. Chrome does an "intervention" on this, which overrides the spec setting.

    See this post for a full explanation: Why doesn't flex item shrink past content size?

    The flex-shrink: 0 approach is a solid cross-browser solution.

  • The margin on the last item collapses.

    This likely happens because the containing block is "over-constrained".

    See this post for a full explanation and solutions: Last margin / padding collapsing in flexbox

Upvotes: 3

Related Questions