Chrome / Safari не заполняет 100% высоты родительского элемента flex
Я хочу иметь вертикальное меню с определенной высотой.
Каждый ребенок должен заполнить рост родителя и иметь текст, выровненный по центру.
Количество детей случайное, поэтому мне приходится работать с динамическими значениями.
Div .container
содержит случайное количество детей (.item
), которые всегда должны заполнить рост родителя. Для этого я использовал flexbox.
Для создания ссылок с текстом, выровненным по середине, я использую display: table-cell
техника. Но использование табличных дисплеев требует использования высоты 100%.
Моя проблема в том что .item-inner { height: 100% }
не работает в WebKit (Chrome).
- Есть ли решение этой проблемы?
- Или есть другая техника, чтобы сделать все
.item
заполнить высоту родительского текста текстом, выровненным по центру?
Пример здесь jsFiddle, должен быть просмотрен в Firefox и Chrome
.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>
4 ответа
Эта проблема
Моя проблема в том что
.item-inner { height: 100% }
не работает в WebKit (Chrome).
Это не работает, потому что вы используете процентную высоту таким образом, который не соответствует традиционной реализации спецификации.
10.5 Высота содержимого:
height
имуществопроцент
Определяет процентную высоту. Процент рассчитывается относительно высоты содержащего блока сгенерированного блока. Если высота содержащего блока не указана явно, и этот элемент не является абсолютно позиционированным, значение вычисляется какauto
,авто
Высота зависит от значений других свойств.
Другими словами, чтобы процентная высота работала с дочерним потоком, родительский объект должен иметь установленную высоту.
В вашем коде контейнер верхнего уровня имеет определенную высоту: .container { height: 20em; }
Контейнер третьего уровня имеет определенную высоту: .item-inner { height: 100%; }
Но между ними контейнер второго уровня - .item
- не имеет определенной высоты. Webkit видит это как недостающую ссылку.
.item-inner
говорит Chrome: дай мне height: 100%
, Хром смотрит на родителя (.item
) для справки и отвечает: 100% чего? Я ничего не вижу (игнорируя flex: 1
Правило, которое есть). В результате это относится height: auto
(высота содержимого), в соответствии со спец.
Firefox, с другой стороны, теперь принимает высоту изгиба родителя как ссылку на процентную высоту ребенка. IE11 и Edge также допускают гибкие высоты.
Также 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
элементы иногда терпят неудачу как гибкие контейнеры, они могут быть гибкими элементами. Рассмотреть вопрос о создании 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
к гибкому элементу (.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
У меня сработало указание атрибута flex для контейнера:
.container {
flex: 0 0 auto;
}
Это гарантирует, что высота установлена и не увеличивается.
Решение: Удалить height: 100%
in .item-inner and add display: flex
in .item
Для мобильного Safari Есть исправление браузера. вам нужно добавить -webkit-box для устройств iOS.
Ex.
display: flex;
display: -webkit-box;
flex-direction: column;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-webkit-flex-direction: column;
align-items: stretch;
если вы используете align-items: stretch;
свойство для родительского элемента, удалите height : 100%
от дочернего элемента.
У меня была похожая проблема в iOS 8, 9 и 10, и информация, приведенная выше, не могла ее исправить, однако я нашел решение после дня работы над этим. Конечно, это не будет работать для всех, но в моем случае мои элементы были сложены в столбец и имели нулевую высоту, когда это должна была быть высота содержимого. Переключение css на row и wrap устранило проблему. Это работает, только если у вас есть один предмет, и они сложены, но, так как мне потребовался день, чтобы выяснить это, я решил поделиться своим исправлением!
.wrapper {
flex-direction: column; // <-- Remove this line
flex-direction: row; // <-- replace it with
flex-wrap: wrap; // <-- Add wrapping
}
.item {
width: 100%;
}
У меня была похожая ошибка, но при использовании фиксированного числа для высоты, а не в процентах. Это также был гибкий контейнер внутри тела (не имеющий заданной высоты). Оказалось, что в Safari мой гибкий контейнер по какой-то причине имел высоту 9 пикселей, но во всех других браузерах он отображал правильную высоту 100 пикселей, указанную в таблице стилей.
Мне удалось заставить его работать, добавив оба height
а также min-height
свойства в класс CSS.
Следующее работало для меня как в Safari 13.0.4, так и в Chrome 79.0.3945.130:
.flex-container {
display: flex;
flex-direction: column;
min-height: 100px;
height: 100px;
}
Надеюсь это поможет!