Решение
Используйте вложенные гибкие контейнеры.
Избавьтесь от высоты в процентах. Избавьтесь от свойств таблицы. Избавиться от vertical-align
. Избегайте абсолютного позиционирования. Просто придерживайтесь flexbox до конца.
Примените display: flex
к элементу flex ( .item
), превратив его в контейнер flex. Это автоматически устанавливает align-items: stretch
, что говорит child ( .item-inner
) увеличить полную высоту родителя.
Важное замечание: Удалите указанные высоты из гибких элементов, чтобы этот метод работал. Если у ребенка указана высота (например 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
объяснение
Моя проблема в том, что .item-inner { height: 100% }
не работает в webkit (Chrome).
Это не работает, потому что вы используете процентную высоту таким образом, который не соответствует традиционной реализации спецификации.
10.5 Высота содержимого: height
свойство
процент
Указывает процентную высоту. Процент рассчитывается относительно высоты содержащего блока сгенерированного блока. Если высота содержащего блока не указана явно, и этот элемент не является абсолютно позиционированным, значение вычисляется в auto
.
auto
Высота зависит от значений других свойств.
Другими словами, чтобы высота в процентах работала с дочерним объектом в потоке, родитель должен иметь заданную высоту.
В вашем коде контейнер верхнего уровня имеет определенную высоту: .container { height: 20em; }
Контейнер третьего уровня имеет определенную высоту: .item-inner { height: 100%; }
Но между ними контейнер второго уровня .item
- не имеет определенной высоты. Webkit видит это как недостающую ссылку.
.item-inner
говорит Chrome: дай мнеheight: 100%
. Chrome смотрит на parent ( .item
) для справки и отвечает: 100% чего? Я ничего не вижу (игнорируя существующее там flex: 1
правило). В результате применяется height: auto
(высота содержимого), в соответствии со спецификацией.
Firefox, с другой стороны, теперь принимает высоту изгиба родителя как ссылку на процентную высоту ребенка. IE11 и Edge также допускают гибкие высоты.
Кроме того, Chrome примет flex-grow
как адекватную родительскую ссылку, если используется вместе сflex-basis
(любое числовое значение работает ( auto
не будет), в том числе 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
собственность.
Подробнее здесь: Работа со height
свойством CSS и процентными значениями
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
элементы иногда терпят неудачу как гибкие контейнеры , они могут быть гибкими элементами. Подумайте о том, чтобы 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. Вложенные гибкие контейнеры (рекомендуется)
Избавьтесь от высоты в процентах. Избавьтесь от свойств таблицы. Избавиться от vertical-align
. Избегайте абсолютного позиционирования. Просто придерживайтесь flexbox до конца.
Примените display: flex
к элементу flex ( .item
), превратив его в контейнер flex. Это автоматически устанавливает align-items: stretch
, что говорит child ( .item-inner
) увеличить полную высоту родителя.
Важное замечание: Удалите указанные высоты из гибких элементов, чтобы этот метод работал. Если у ребенка указана высота (например 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>