Search code examples
htmlcssfirefoxflexbox

Why does flex child element reserve vertical space only on Firefox?


Repro steps:

  1. Go to https://codepen.io/zelliottm/pen/bGQmBKQ on Firefox (latest).
  2. Observe that the <custom> element is taking up a small amount of space at the bottom of the scrollable region.

Any of the following changes prevent this element from taking up space:

  • Remove the nested <custom> element
  • Add custom { display: block; }
  • Add custom { font-size: 0; }

This behavior does not repro on Chrome or Safari (latest). I'm looking to better understand why Firefox has this different behavior. If you're able to link to an outstanding Firefox bug or SO question that this is essentially a dupe of, that'd be great. Thank you!

body {
  background: blue;
  margin: 0;
}

#container {
  background: red;
  display: flex;
  flex-direction: column;
}

#inner {
  height: 1000px;
}
<div id="container">
  <div id="inner">Hello!</div>
  <custom>
    <custom></custom>
  </custom>
</div>


Solution

  • It seems that while Chromium and Webkit are doing the intuitive thing, Firefox is behaving strictly correct to the specification.

    Adjusting the example slightly while keeping the difference in behaviour, consider this:

    html {
      background:yellow;
      outline: 1px solid black;
    }
    
    body {
      background: blue;
      margin: 0;
    }
    
    #container {
      background: red;
    }
    
    #inner {
      height: 1000px;
    }
    <div id="container">
      <div id="inner">Hello!</div>
      <div><span></span></div>
    </div>

    The span creates an inline box in the box tree, which then has to be laid out in a line box in the inline formatting context established by its containing div. But the CSS 2 spec says:

    Line boxes are created as needed to hold inline-level content within an inline formatting context. Line boxes that contain no text, no preserved white space, no inline elements with non-zero margins, padding, or borders, and no other in-flow content (such as images, inline blocks or inline tables), and do not end with a preserved newline must be treated as zero-height line boxes for the purposes of determining the positions of any elements inside of them, and must be treated as not existing for any other purpose.

    The line box meets those requirements. So for the purpose of laying out the span, it is treated as zero height. The span, as an inline element with non-zero font-size overflows its containing div (above and) below it. You can see from the background and the outline that it in fact overflows the #container element, the body element and the root element as well.

    But the viewport scroll shows the whole of the scrollable overflow area. Effectively, this amounts to everything painted onto the canvas in the positive x, y space.

    This includes the span that overflows the root element leading to the extra reserved space you see at the bottom in Firefox.