Рішення
Використовуйте вкладені гнучкі контейнери.
Позбавтеся від відсоткової висоти. Позбавтеся від властивостей таблиці. Позбутися vertical-align
. Уникайте абсолютного позиціонування. Просто дотримуйтесь флексбоксу весь шлях.
Нанесіть display: flex
на гнучкий елемент ( .item
), зробивши його гнучким контейнером. Це автоматично встановлюється align-items: stretch
, що говорить дитині ( .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% }
не працює у веб-програмі (Chrome).
Це не працює, оскільки ви використовуєте відсоткову висоту таким чином, що не відповідає традиційній реалізації специфікації.
10.5 Висота вмісту: height
властивість
процент
Вказує відсоткове зростання. Відсоток обчислюється відносно висоти сформованого блоку, що містить блок. Якщо висота блоку, що містить, не вказана явно і цей елемент не розташований абсолютно, значення обчислюється до auto
.
auto
Висота залежить від значень інших властивостей.
Іншими словами, для відсоткової висоти для роботи над дитиною, що надходить, батько повинен мати задану висоту.
У вашому коді контейнер верхнього рівня має певну висоту: .container { height: 20em; }
Контейнер третього рівня має визначену висоту: .item-inner { height: 100%; }
Але між ними контейнер другого рівня - .item
- не має визначеної висоти. Webkit сприймає це як посилання, що відсутнє.
.item-inner
говорить Chrome: дай меніheight: 100%
. Chrome звертається до батьків ( .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. Вкладені контейнери Flex (рекомендується)
Позбавтеся від відсоткової висоти. Позбавтеся від властивостей таблиці. Позбутися vertical-align
. Уникайте абсолютного позиціонування. Просто дотримуйтесь флексбоксу весь шлях.
Нанесіть display: flex
на гнучкий елемент ( .item
), зробивши його гнучким контейнером. Це автоматично встановлюється align-items: stretch
, що говорить дитині ( .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>