Prevent flex item from exceeding parent height and make scroll bar work

Short Answer

Instead of flex: 1, use flex: 1 1 1px.

Make these two adjustments in your code:

#messagelist {
        /* flex:1; */
        flex: 1 1 1px; /* new */
    }

#messagecontents {
        /* flex:1; */
        flex: 1 1 1px; /* new */
    }

revised codepen


Explanation

In most cases, as you have noted, adding min-height: 0 to flex items in a column-direction container is enough to correct the problem.

In this case, however, there’s an additional obstacle: flex-basis.

You’re applying the following rule to flex items #messagelist and #messagecontents: flex: 1.

This is a shorthand rule that breaks down to:

  • flex-grow: 1
  • flex-shrink: 1
  • flex-basis: 0

(source: https://www.w3.org/TR/css-flexbox-1/#flex-common)


2019 UPDATE: Since the posting of this answer in 2018, it appears that Chrome’s behavior has changed and is now uniform with Firefox and Edge. Please keep that in mind as you read the rest of this answer.


In Chrome, flex-basis: 0 is enough to trigger an overflow, which generates the scrollbars. (2019 update: This may no longer be the case.)

In Firefox and Edge, however, a zero flex-basis is insufficient. This is probably the more correct behavior in terms of standards compliance as MDN states:

In order for overflow to have an effect, the block-level container must have either a set height (height or max-height) or white-space set to nowrap.

Well, flex-basis: 0 meets none of those conditions, so an overflow condition should not occur. Chrome has probably engaged in an intervention (as they often do).

An intervention is when a user agent decides to deviate slightly from a standardized behavior in order to provide a greatly enhanced user experience.

To meet the “standardized behavior”, which would enable an overflow to occur in Firefox and Edge, give flex-basis a fixed height (even if it’s just 1px).

Leave a Comment