Неверная высота в flexbox элементах в Chrome

У меня есть тонкая проблема для любого гуру CSS там. Мой зеленый div имеет гибкую высоту, занимая оставшиеся. И теперь я хочу поставить div внутри этого div, который должен быть половиной зеленого div. Но похоже, что Chrome относится к нему как к половине всей страницы, а не к элементу flex.

http://jsfiddle.net/unh5rw9t/1/

HTML

<body>
    <div id="wrapper">
        <div id="menu">
            1
        </div>
        <div id="content">2
            <div id="half_of_content">2.1</div>
        </div>
        <div id="footer" style="">
            3
        </div>
    </div>
</body>

CSS

html,body {
    height: 100%;
    margin: 0;
}

#wrapper {
    display: flex;
  flex-flow: column;
    height: 100%;
}

#menu {
    height: 70px; 
    background-color: purple
}

#content {
    flex: 1;
    height: 100%;
    background-color: green;
}

#half_of_content {
    height: 50%;
    background-color: yellow;
}

#footer {
    height: 100px; 
    background-color: cyan
}

Ответы

Ответ 1

Вы можете полностью позиционировать div id="half_of_content".

#content {
    flex: 1;
    height: 100%;
    background-color: green;
    position: relative; /* new */
}

#half_of_content {
    height: 50%;
    background-color: yellow;
    position: absolute; /* new */
    width: 100%; /* new */
}

DEMO

Что касается вашего заявления:

Но похоже, что Chrome относится к нему как к половине всей страницы а не элемент гибкости.

Вы дали body a height: 100%. Затем дал свой ребенок (.wrapper) a height: 100%. Затем дал свой ребенок (.content) a height: 100%. Таким образом, они равны по высоте. Предоставление следующего ребенка (#half_of_content) a height: 50%, естественно, будет 50% высоты body.

Однако при абсолютном позиционировании вам не нужно указывать высоты родителей.

Ответ 2

@Michael_B объяснил, почему Chrome ведет себя следующим образом:

Вы дали body a height: 100%. Затем дал своему ребенку (.wrapper) a height: 100%. Затем дал свой ребенок (.content) a height: 100%. Таким образом, они равны по высоте. Предоставление следующего ребенка (#half_of_content) a height: 50%, естественно, будет 50% высоты body.

Однако Firefox не согласен с тем, что в действительности height: 100% of .content игнорируется, а его высота вычисляется в соответствии с flex: 1.

То есть, Chrome разрешает процент по отношению к значению родительского свойства height. Firefox делает это в отношении разрешенной гибкой высоты родителя.

Правильное поведение - это Firefox. Согласно Определенные и неопределенные размеры,

Если процент будет разрешен против flex item s основной размер, а flex item имеет definite flex основы, а flex container имеет definite main размер, flex item s основной размер следует рассматривать как definite с целью разрешения процента, а также процент должен быть разрешен против сгибаемого основного размера flex item (то есть после того, как алгоритм компоновки ниже был завершено для flex item flex container и flex элемент получил свой окончательный размер).

Ниже приведено обходное решение для Chrome:

#content {
  display: flex;
  flex-direction: column;
}
#content::after {
  content: '';
  flex: 1;
}
#half_of_content {
  flex: 1;
  height: auto;
}

Таким образом, доступное пространство в #content будет равномерно распределено между #half_of_content и псевдоэлементом ::after.

Предполагая, что #content не имеет другого содержимого, #half_of_content будет 50%. В вашем примере у вас есть 2, поэтому он будет немного меньше 50%.

html,
body {
  height: 100%;
  margin: 0;
}
#wrapper {
  display: flex;
  flex-flow: column;
  height: 100%;
}
#menu {
  height: 70px;
  background-color: purple
}
#content {
  flex: 1;
  height: 100%;
  background-color: green;
  display: flex;
  flex-direction: column;
}
#content::after {
  content: '';
  flex: 1;
}
#half_of_content {
  flex: 1;
  background-color: yellow;
}
#footer {
  height: 100px;
  background-color: cyan
}
<div id="wrapper">
  <div id="menu">
    1
  </div>
  <div id="content">2
    <div id="half_of_content">2.1</div>
  </div>
  <div id="footer" style="">
    3
  </div>
</div>

Ответ 3

Вложенные flexboxes являются немного ошибками. Я немного переработал вашу разметку, добавив внутреннюю оболочку с display: flex;, которая, похоже, выполняет эту работу. Вот fiddle (также используя имена классов вместо ids).

<div class="content">
  <div class="wrapper-inner">
    2
    <div class="half">
      2.1
    </div>
  </div>
</div>

.wrapper-inner {
    position: absolute;
    display: flex;
    flex-direction: column;
    height: 100%;
    width: 100%;
}

Ответ 4

Fix:

on #content set

display: flex; 
flex-flow: column nowrap; 
justify-content: flex-end

on #half_of_content set flex: 0 0 50%;

Предостережение: вам нужно добавить div extra как дочерний элемент #content.

Вот полный пример:

html,body {
    height: 100%;
    margin: 0;
}

#wrapper {
    display: flex;
  flex-flow: column;
    height: 100%;
}

#menu {
    height: 70px; 
    background-color: purple
}

#content {
    flex: 1;
    height: 100%;
    display:flex;
    flex-flow: column nowrap;
    justify-content: flex-end;
    background-color: green;
}

#half_of_content {
    flex: 0 0 50%;
    background-color: yellow;
}

#footer {
    height: 100px; 
    background-color: cyan
}
<body>
    <div id="wrapper">
        <div id="menu">
            1
        </div>
        <div id="content">2
            <div id="half_of_content">2.1</div>
        </div>
        <div id="footer" style="">
            3
        </div>
    </div>
</body>