3

In this setup:

html,
body {
  height: 100%;
}

.app {
  display: flex;
}

.menu {
  background-color: red;
  width: 100px;
}

.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>

I have two questions.

  1. You can see height of menu is same as height of content, right? Can someone explain why this is? Did it inherit height of app (height of which was dynamically calculated based on content of content div)?

  2. If I insert height: 100% inside .menu properties, like this:

.menu {
            background-color: red;
            width: 100px;
            height: 100%
      }

then height of menu is reduced. Can someone explain why this is the case? If menu was supposed to inherit height of app as in the previous case, then why writing height:100% prevented this?

Temani Afif
  • 245,468
  • 26
  • 309
  • 415
  • Your menu's height flexes to take all the space by default, setting it to 100% will make it 100% of it's content (100% of your "menu" text) – Daniel Vafidis Jan 19 '19 at 21:06
  • 1
    @DanielVafidis it's wrong, 100% doesn't mean 100% of it's content but it's parent element (containing block) but this rule will fail because there is no height set on the parent element. – Temani Afif Jan 19 '19 at 21:16

1 Answers1

2

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.

Temani Afif
  • 245,468
  • 26
  • 309
  • 415
  • ```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 container```->But height of container was not known/specified initially right? (Rather calculated afterwards depending on content of ```content``` div) –  Jan 19 '19 at 21:10
  • @jdoe yes but there is content inside it that will define this height, so basically the biggest element will define the height of all the elements – Temani Afif Jan 19 '19 at 21:12
  • Yes I meant height of "app" wasn't known initially right? So first ```app``` adapted its height based on ```content``` div and then menu inherited it? –  Jan 19 '19 at 21:14
  • @jdoe it's not inheritance, it's a stretching alignment. We told the element to stretch if there is space left BUT with height:100% it's different, we told the element to take the height of the container as a reference but there is no height set, so it will fail – Temani Afif Jan 19 '19 at 21:15
  • ah so menu didn't inherit height from app? –  Jan 19 '19 at 21:19
  • Final question. btw does child div ever inherit height of parent? –  Jan 19 '19 at 21:21
  • 1
    @jdoe no they never inherit height, the height is always auto by default (height of content) and only some properties will create this kind of inheritance like the stretch effect of flexbox or height:100% ONLY when the parent as a height specified – Temani Afif Jan 19 '19 at 21:22
  • Interestingly here, https://textuploader.com/1a7wh, ```.test``` inherited height from ```.content```,even though ```.content``` hadn't height specified as you claim in above comment, isn't it? –  Jan 19 '19 at 21:40
  • I was talking about ```.test``` and ```.content``` in that example. Btw. ```.test``` is child of ```.content``` isn't it? Why siblings? and I meant apparently ```.test``` again inherited height of ```.content``` isn't it? But you said it wouldn't if parent hadn't height specified, which ```.content``` didn't. –  Jan 19 '19 at 21:46
  • @jdoe sorry my mistake .. I saw it wrong. In this case you are facing a particular case ;) I will gather you the link to read about – Temani Afif Jan 19 '19 at 21:48
  • THanks I will appreciate. I am still learning CSS and it seems to get tricky sometimes :) –  Jan 19 '19 at 21:50
  • @jdoe I wrote a *long* answer about such behavior where the spec is not respected or more precisely not well interpreted (https://stackoverflow.com/a/52137966/8620333). Indeed in this case there is no height set but the stretch effect is somehow setting that height so yes we can say that element has a height set due to the stretch effect. A bit crazy, I have to admit. This happen with Flexbox and CSS grid is some cases – Temani Afif Jan 19 '19 at 21:50
  • @jdoe I also update this answer to include the relevant part you need – Temani Afif Jan 19 '19 at 21:59