Flexbox в Chrome - Как ограничить размер вложенных элементов?

В Google Chrome, как я могу заставить элемент, вложенный внутри члена flexbox (через "member of a flexbox", я имею в виду дочерний элемент с стилем display:flex), чтобы ограничить его размер к размеру члена flexbox, который он вложен? Например, предположим, что у меня есть следующее:

<div style="display:flex; flex-direction:column; height:100vh;">
  <div style="height:60px;">Static header</div>
  <div style="flex: 1 1 0; overflow:hidden;">
     <div style="overflow:auto; height:100%;" id="problem-is-here">
       Lots and lots of content, way too much to fit in the viewport
     </div>
  </div>
</div>

Поскольку первый дочерний div из внешнего div имеет постоянную высоту, он заканчивается ровно на 60 пикселей высотой, а поскольку второй дочерний div имеет flex-grow из 1, он получает остальную часть доступное пространство (в данном случае 100% экрана просмотра минус 60 пикселей). Я могу подтвердить, что размеры этого элемента в соответствии с элементом Inspect Element достаточно велики, чтобы заняться остальной частью пространства просмотра.

В Firefox и IE11 из-за height:100% самый внутренний элемент (id="problem-is-here") принимает высоту, вычисленную для своего родителя. Поэтому, поскольку он слишком мал, чтобы отображать его содержимое, а overflow установлен на auto, он (а не весь body) получает вертикальную полосу прокрутки. Это то, чего я хочу.

В Chrome, однако, самый внутренний элемент отображается с достаточной высотой, чтобы содержать весь его контент, который является большей высотой, чем его родитель. Таким образом, поскольку его родительский элемент имеет overflow:hidden, полосы прокрутки не отображаются, а избыточное содержимое недоступно. Как сообщить Chrome о том, что этот самый внутренний элемент имеет высоту, максимально равную высоте его родительского элемента, когда высота родителя определяется свойством flexbox, а не CSS height? Обратите внимание, что я не могу дать ни внутреннему div, ни его родителю определенное значение height, так как в приложении, над которым я работаю, число других членов flexbox может меняться.

Примечание. Я попробовал несколько предложений из других ответов, таких как установка всех элементов min-height:0 вместо auto или обеспечение flex-basis установлено на 0, но ни один из них не сработал. См.

http://plnkr.co/edit/UBRcrNmR5iDbn3EXu6FI?p=preview

для примера, иллюстрирующего проблему. (div с id heres-the-problem является тем, высота которого я хочу ограничить высотой своего родителя.)

Ответ 1

Сначала давайте рассмотрим терминологию:

... как принудительно вставить элемент, вложенный внутри члена flexbox (через "member of a flexbox", я имею в виду дочерний элемент с стилем display:flex), чтобы ограничить его размер до размер члена flexbox, который он вложил?

Элемент с display: flex называется контейнером flex (технически) или гибким родителем (разговорно).

Дети гибкого контейнера называются гибкими элементами. Обратите внимание на слово children (первый уровень). Потомки гибкого контейнера за пределами детей не являются гибкими элементами, и большинство свойств гибкости не относятся к ним.


Теперь, обращаясь к вашему вопросу:

Проблема заключается в том, что Firefox (и, по-видимому, IE11) имеет другую интерпретацию правила высоты над уровнем, чем Chrome.

В частности, вертикальная полоса прокрутки, которую вы хотите, не отображается в Chrome, потому что вы используете процентные высоты таким образом, который не соответствует традиционной реализации спецификации.

Свойство CSS height

процент
Определяет процентную высоту. Процент вычисляется относительно высоты генерируемого блока, содержащего блок. Если высота содержащего блока явно не указана, и этот элемент не является абсолютно позиционированным, значение вычисляется как "авто".

auto
Высота зависит от значений других свойств.

Другими словами, если вы хотите, чтобы элемент имел процентную высоту, вы должны указать высоту в содержащем блоке (то есть родительском).

В вашем коде body (уровень 1) есть height: 100vh.

Один уровень вниз, .max-flex (уровень 2) имеет height: 100%.

Четыре уровня вниз, .large-nested-div (уровень 4) имеет height: 100%.

Однако в .variable-flex-content (уровень 3) не существует свойства height. Вы определяете высоту с помощью flex: 1 1 0. Что касается Chrome, это недостающее звено в цепочке и нарушение спецификации. Chrome ожидает увидеть свойство height, а когда нет, он вычисляет высоту до auto.


Chrome vs Firefox (я не тестировал IE11, поэтому я не буду упоминать об этом здесь)

Традиционно при вычислении процентных высот браузеры интерпретировали использование спецификации термина "высота" для обозначения значения свойства height. Его также можно легко интерпретировать как высоту (общий термин), но требование свойства height стало преобладающей реализацией. Я никогда не видел, чтобы min-height или max-height работали над родителем при работе с высотами процента.

В последнее время, как уже отмечалось в этом вопросе, и другой и другой, Firefox расширился его интерпретация для принятия высот flex.

Непонятно, какой браузер более совместим.

Не имеет значения, что определение свойства height не обновлялось с 1998 года (CSS2).


Решение

Вместо определения высоты .variable-flex-content с помощью flex: 1 1 0% используйте height: 100% или height: calc(100% - 60px) или абсолютное позиционирование.