Chrome / Safari не заполняет 100% высоту родителя flex
Я хочу иметь вертикальное меню с определенной высоты.
каждый ребенок должен заполнить высоту родителя и иметь выровненный по середине текст.
количество детей является случайным, поэтому мне приходится работать с динамическими значениями.
Div .container
содержит случайное число детей (.item
), которые всегда должны заполнить высоту родителя. Для этого я использовал flexbox.
для создания ссылок с текстом, выровненным по середине, я использую display: table-cell
метод. Но использование табличных дисплеев требует использования высоты 100%.
моя проблема в том, что .item-inner { height: 100% }
не работает в webkit (Chrome).
- есть ли решение этой проблемы?
- или есть другая техника, чтобы сделать все
.item
заполните высоту родителя текстом, выровненным по вертикали до середины?
пример здесь jsFiddle, следует просмотреть в Firefox и Хром
.container {
height: 20em;
display: flex;
flex-direction: column;
border: 5px solid black
}
.item {
flex: 1;
border-bottom: 1px solid white;
}
.item-inner {
height: 100%;
width: 100%;
display: table;
}
a {
background: orange;
display: table-cell;
vertical-align: middle;
}
<div class="container">
<div class="item">
<div class="item-inner">
<a>Button</a>
</div>
</div>
<div class="item">
<div class="item-inner">
<a>Button</a>
</div>
</div>
<div class="item">
<div class="item-inner">
<a>Button</a>
</div>
</div>
</div>
3 ответов
Проблема
моя проблема в том, что
.item-inner { height: 100% }
не работает в webkit (Chrome).
это не работает, потому что вы используете процентную высоту таким образом, который не соответствует традиционной реализации спецификации.
10.5 высота содержимого:
height
свойствапроцент
задает высоту в процентах. Этот процент рассчитывается относительно высоты генерируемого бокса содержащий блок. Если высота содержащего блока не указан явно и этот элемент не является абсолютно позиционированным, значение вычисляется доauto
.авто
высота зависит от значений других свойств.
другими словами, для процентной высоты для работы с дочерним потоком в потоке родитель должны есть набор высота.
в вашем коде контейнер верхнего уровня имеет определенную высоту:.container { height: 20em; }
контейнер третьего уровня имеет определенную высоту:.item-inner { height: 100%; }
но между ними, контейнер второго уровня -.item
– не иметь определенную высоту. Webkit видит это как недостающее звено.
.item-inner
говорит Chrome:дайте мне height: 100%
. Chrome смотрит на родителя (.item
) для справки и отвечает: 100% и что? Я ничего не вижу!--76--> (игнорируя flex: 1
правило, есть). В результате, он применяется height: auto
(высота содержания), в соответствии с спецификациями.
Firefox, с другой стороны, теперь принимает высоту flex родителя в качестве ссылки для высоты процента ребенка. IE11 и край принимают высоты гибкого трубопровода, также.
кроме того, Chrome примет flex-grow
как адекватная родительская ссылка если используется в сочетании с flex-basis
(любое значение, в том числе flex-basis: 0
). Однако на момент написания этой статьи это решение не работает в Safari.
#outer {
display: flex;
flex-direction: column;
height: 300px;
background-color: white;
border: 1px solid red;
}
#middle {
flex-grow: 1;
flex-basis: 1px;
background-color: yellow;
}
#inner {
height: 100%;
background-color: lightgreen;
}
<div id="outer">
<div id="middle">
<div id="inner">
INNER
</div>
</div>
</div>
решений
1. Укажите высоту для всех родительских элементов
надежным кросс-браузерным решением является указание высоты на всех родительских элементах. Это предотвращает недостающие ссылки, которые браузеры на основе Webkit считают нарушением спекуляция.
обратите внимание, что min-height
и max-height
не приемлемы. Это должно быть height
собственность.
подробнее здесь: работа с CSS height
свойства и процентные значения
2. CSS относительное и абсолютное позиционирование
применить position: relative
к родителю и position: absolute
для ребенка.
размер ребенка с height: 100%
и width: 100%
, или используйте свойства смещения: top: 0
, right: 0
, bottom: 0
, left: 0
.
при абсолютном позиционировании процентная высота работает без заданной высоты на родителе.
3. Удалите ненужные HTML-контейнеры (рекомендуется)
есть ли необходимость в двух контейнерах вокруг button
? Почему бы не удалить .item
или .item-inner
, или оба? Хотя button
элементы иногда терпят неудачу как контейнеры flex, они могут быть гибкие элементы. Подумайте о создании button
ребенок .container
или .item
, и удаление безвозмездной наценки.
вот пример:
.container {
height: 20em;
display: flex;
flex-direction: column;
border: 5px solid black
}
a {
flex: 1;
background: orange;
border-bottom: 1px solid white;
display: flex; /* nested flex container (for aligning text) */
align-items: center; /* center text vertically */
justify-content: center; /* center text horizontally */
}
<div class="container">
<a>Button</a>
<a>Button</a>
<a>Button</a>
</div>
4. Вложенные контейнеры Flex (рекомендуется)
избавиться от процентных высот. Избавьтесь от свойств таблицы. Избавиться от vertical-align
. Избежать абсолютного позиционирования. просто придерживайтесь flexbox полностью через.
применить display: flex
к пункту флекс (.item
), что делает его контейнер. Это автоматически устанавливает align-items: stretch
, который говорит ребенку (.item-inner
), чтобы расширить полную высоту родителя.
важно: удалите указанные высоты из элементов flex для работы этого метода. если у ребенка указана высота (например,height: 100%
), то он будет игнорировать align-items: stretch
исходящий от родителя. Для stretch
по умолчанию работает, высота ребенка должен вычислить до auto
(полное объяснение).
попробуйте это (без изменений в HTML):
.container {
display: flex;
flex-direction: column;
height: 20em;
border: 5px solid black
}
.item {
display: flex; /* new; nested flex container */
flex: 1;
border-bottom: 1px solid white;
}
.item-inner {
display: flex; /* new; nested flex container */
flex: 1; /* new */
/* height: 100%; <-- remove; unnecessary */
/* width: 100%; <-- remove; unnecessary */
/* display: table; <-- remove; unnecessary */
}
a {
display: flex; /* new; nested flex container */
flex: 1; /* new */
align-items: center; /* new; vertically center text */
background: orange;
/* display: table-cell; <-- remove; unnecessary */
/* vertical-align: middle; <-- remove; unnecessary */
}
<div class="container">
<div class="item">
<div class="item-inner">
<a>Button</a>
</div>
</div>
<div class="item">
<div class="item-inner">
<a>Button</a>
</div>
</div>
<div class="item">
<div class="item-inner">
<a>Button</a>
</div>
</div>
</div>
jsFiddle
У меня была аналогичная проблема в iOS 8, 9 и 10, и информация выше не могла ее исправить, однако я обнаружил решение после дня работы над этим. Конечно, это не будет работать для всех, но в моем случае мои элементы были сложены в столбец и имели высоту 0, когда она должна была быть высотой содержимого. Переключение css на строку и wrap исправило проблему. Это работает, только если у вас есть один элемент, и они сложены, но так как мне потребовался день, чтобы узнать это, я подумал, что должен поделиться своим исправить!
.wrapper {
flex-direction: column; // <-- Remove this line
flex-direction: row; // <-- replace it with
flex-wrap: wrap; // <-- Add wrapping
}
.item {
width: 100%;
}