3

Let's say we have this markup:

<div id="outer">
  <div id="middle">
    <div id="inner">
    </div>
  </div>
</div>

and this css:

#outer {
  display: flex;
  flex-direction: column;
  background-color: white;
  height: 300px;
}

#middle {
  flex-grow: 1;
  background-color: beige;
}

#inner {
  background-color: black;
  height: 100%;
}

I would expect the inner div to span the whole 300 pixel, as it should be as high as the middle flex item which in turn fills its parent.

That's the behavior I see on IE, Edge and Firefox.

On Chrome, the middle div still fills the 300 pixel, but the inner div is as high as it would be without any height attribute.

See this fiddle: https://jsfiddle.net/mhjussna/

That's a bug in Chrome, right?

John
  • 6,693
  • 3
  • 51
  • 90
  • `height:100%` will be buggy using flex. instead use `align-items: stretch` on `#outer` element. – Farzad Yousefzadeh Aug 17 '16 at 09:33
  • `align-item` is for horizontal alignment when `flex-direction` is `column - so it has no bearing on the question. Also note I don't use `height: 100%` on any of the elements that participate directly in flex layouting. – John Aug 17 '16 at 09:42

2 Answers2

5

It's because you are just using flex-grow:1 on the #middle div.

If you use the recommended shorthand of flex:1...it works perfectly.

#outer {
  display: flex;
  flex-direction: column;
  background-color: white;
  height: 300px;
}
#middle {
  flex: 1;
  /* here */
  background-color: beige;
}
#inner {
  background-color: black;
  height: 100%;
  color: white;
}
<div id="outer">
  <div id="middle">
    <div id="inner">
      x
    </div>
  </div>
</div>

Alternatively, state all the flex values

#middle {
  flex-grow: 1;
  flex-shrink:0;
  flex-basis:0;
  background-color: beige;
}

JSfiddle Demo

Paulie_D
  • 107,962
  • 13
  • 142
  • 161
  • It works, not because you're using the `flex` property *per se*, but because Chrome allows for `flex-grow` in conjunction with `flex-basis` to serve as the parent reference height for a child's percentage height. Either property alone would fail to complete the task. *Just note that this solution doesn't work in Safari.* Still, this answer is revealing and highlights an important discrepancy in webkit browsers. I've updated my answer in the dupe. Thanks. – Michael Benjamin Aug 17 '16 at 13:26
0

I do not think that it is a bug in Chrome.

From W3C recommendation https://www.w3.org/TR/CSS2/visudet.html#the-height-property :

Specifies a percentage height. The percentage is calculated with respect to the height of the generated box's containing block. If the height of the containing block is not specified explicitly (i.e., it depends on content height), and this element is not absolutely positioned, the value computes to 'auto'.

If you set height: 100% for #middle, you get same result that in other browsers https://jsfiddle.net/mhjussna/1/ .

Sergey Ratnikov
  • 1,296
  • 8
  • 12
  • But the height of the containing block doesn't depend on content height (which is zero in this case), and even Chrome agrees with that. The height is set explicitly, not with a height attribute, but with a flex-grow attribute. – John Aug 17 '16 at 09:38
  • Also, setting `height: 100%` for `#middle` is no workaround as it totally defeats flex layouting: What if I have another flex child? – John Aug 17 '16 at 09:43
  • I think if we have two middle elements with inner elements height 100%, the 100% means 300 not 150px. You may use position absolute with top:0, right:0, bottom: 0, left: 0 instead height 100% https://jsfiddle.net/6xj7zrLv/ – Sergey Ratnikov Aug 17 '16 at 09:56
  • Had cases where the absolute positioning doesn't work. Iframes I believe, could remember wrong though. – John Aug 17 '16 at 09:58