This is a particular case where the browser can handle percentage value on height due to the stretch effect of flexbox. The flex-child
has a default alignment equal to stretch which is equivalent to having height:100%
then the flex-parent
is also filling its parent height with flex-grow:1
. At the end, the browser was able to correctly resolve the height:100%
of flex-grand-child
If the flex item has align-self: stretch
, redo layout for its contents, treating this used size as its definite cross size so that percentage-sized children can be resolved.ref
If you disable the stretch alignment, it will break:
html,
body {
height: 100%;
}
.container {
display: flex;
flex-direction: column;
height: 100%;
}
.flex-parent {
flex: 1 0 auto;
display: flex;
}
.flex-child {
width: 300px;
min-height: 200px;
align-self: flex-start; /*this will break it*/
border: 1px solid;
}
.flex-grand-child {
height: 100%;
background-color: green;
}
<div class="container">
<div class="flex-parent">
<div class="flex-child">
<div class='flex-grand-child'></div>
</div>
</div>
</div>
To use simple words: When having the stretch effect, the browser will first define the parent height based on its own parent (the content play no role here) then the browser will make the content height:100%
of the previous calculated height. Without stretch the browser need to consider the content to define the height of the parent and here we will fall into the classic issue of percentage height.
Related question to get more cases where percentage can be resolved without having an explicit height defined on the parent element: Why is my Grid element's height not being calculated correctly?
Here is the relevant part of the specification dealing with this: https://www.w3.org/TR/css-sizing-3/#percentage-sizing
It's a bit complex but it's different from the CSS2 specification where percentage will always fail if the parent height is not specified:
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'.