Search code examples
cssflexboxoverflowcss-positionmargin

CSS Flexbox: a centered child overflows a parent with position fixed


How can I properly center the #content without overflowing the #container? margin: auto kinda works, but looks like a hack to me, I would like not to use any margins with CSS Flexbox.

Keep in mind that the #container has position: fixed.

Here's the code demonstrates the issue: [View in JSFiddle ↗]

document.getElementById('content').innerHTML = [...Array(100).keys()].join('<br>')
#container {
  position: fixed;
  background: lightblue;
  top: 0; bottom: 0;
  left: 0; right: 0;

  display: flex;
  align-items: center;
  justify-content: center;
  overflow: auto;
}

#content {
  border: 1px solid green;
  /* uncomment the hack below to get desired behavior */
  /* margin: auto */
}
<div id="container">
  <div id="content">
  </div>
</div>

Desired behavior you can check with uncommenting margin: auto, question is how to achieve the same result with only flex- properties and without margin: auto.


Solution

  • Without a markup change you can't, as when using align-items: center, it by design overflow in both directions if the content exceed the flex container.

    ‘center’
        The flex item’s margin box is centered in the cross axis within the line. (If the cross size of the     flex line is less than that of the flex item, it will overflow equally in both directions.)

    Also note that auto margins has a special meaning in Flexbox, and it is not a hack, quite the opposite, so in this case, they are the flex based solution to accomplish exactly that.

    Update: Here's a later answer of mine, showing a few more solutions, inlcuding the new safe keyword: Flexbox align-items overflow text get cuts off at top

    document.getElementById('content').innerHTML = [...Array(100).keys()].join('<br>')
    #container {
      position: fixed;
      background: lightblue;
      top: 0; bottom: 0;
      left: 0; right: 0;
    
      display: flex;
      overflow: auto;
    }
    
    #content {
      border: 1px solid green;
      margin: auto;
    }
    <div id="container">
      <div id="content">
      </div>
    </div>