In this setup:
For the first case, it's about the default alignment of flexbox which is stretch. So all the elements will stretch to fit the height of the container1 thus the menu is having the same height as the content. In other words, the tallest element will define the height and the other will stretch to fit that height.
Change the alignment and you will no more have this behavior:
html,
body {
height: 100%;
}
.app {
display: flex;
align-items:flex-start; /*anything different from stretch*/
}
.menu {
background-color: red;
width: 100px;
height:100%;
}
.content {
flex: 1;
border: 1px solid blue;
}
<div class="app">
<div class="menu">menu</div>
<div class="content">
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
</div>
</div>
By adding height:100%
you now explicitely apply a height to the element (stretch no more apply) but this will fail to auto
value (the height of the content) because the parent element don't have any height specified2
html,
body {
height: 100%;
}
.app {
display: flex;
}
.menu {
background-color: red;
width: 100px;
height:100%;
}
.content {
flex: 1;
border: 1px solid blue;
}
<div class="app">
<div class="menu">menu</div>
<div class="content">
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
</div>
</div>
1 If the cross size property of the flex item computes to auto, and neither of the cross-axis margins are auto, the flex item is stretched. Its used value is the length necessary to make the cross size of the item’s margin box as close to the same size as the line as possible, while still respecting the constraints imposed by min-height/min-width/max-height/max-width.ref
We have only one line in our case so it's the same as the whole container.
2 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'.ref
Add a height to the app and you will see what is happening:
html,
body {
height: 100%;
}
.app {
display: flex;
height:80%;
}
.menu {
background-color: red;
width: 100px;
height:100%;
}
.content {
flex: 1;
border: 1px solid blue;
}
<div class="app">
<div class="menu">menu</div>
<div class="content">
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
<div>content</div>
</div>
</div>
UPDATE
Based on the comments here is a particular case where percentage height is working without height specified in the parent element.
html,
body {
height: 100%;
}
.app {
display: flex;
height: 80%;
}
.menu {
background-color: red;
width: 100px;
}
.container{
flex: 1;
background:green;
}
.test {
height: 80%;
border: 2px solid blue;
}
<div class="app">
<div class="menu">menu</div>
<div class="container">
<div class="test">percentage height is working here!! why??</div>
</div>
</div>
As I explained in a previous answer the height of the .container
is not explicitly set but we don't have any cyclic dependecy because the height of the .container
is defined with the stretch behavior and not his content so the browser can first set the .container
height using stretch then resolve the percentage height of .test
element.
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
Without the stretch effect, the browser need to first find the height based on the content and the content is having a height based on the container thus we have a cyclic dependency which will make the percentage height to fail to auto
in order to be able to define the container height.