Chrome / Safari не заповнює 100% висоту гнучких батьків


235

Я хочу мати вертикальне меню з певною висотою.

Кожна дитина повинна заповнити висоту батьків і мати текст середнього рівня.

Кількість дітей випадкова, тому мені доводиться працювати з динамічними значеннями.

Div .containerмістить випадкову кількість дітей ( .item), які завжди повинні заповнити зріст батьків. Щоб досягти цього, я використовував флексбокс.

Для створення посилань з текстом, вирівняним до середини, я використовую display: table-cellтехніку. Але для використання табличних дисплеїв потрібно використовувати висоту 100%.

Моя проблема полягає в тому, що .item-inner { height: 100% }не працює у веб-програмі (Chrome).

  1. Чи є виправлення цієї проблеми?
  2. Або існує інша техніка, щоб змусити всі .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>


1
тепер це було виправлено - bugs.chromium.org/p/chromium/isissue/detail?id=426898
vsync

3
Це спеціально не стосується ОП, але може бути актуальним для гуглерів, які приземляються тут на "сафарі-дисплей абсолютної висоти 100% не працює" або щось подібне. У мене такий елемент є у внутрішньому контейнері flex, і він повинен був вказати top:0та left:0відобразити його, як очікувалося.
AlexMA

1
@vsync ні зафіксований ще: stackoverflow.com/questions/46226298 / ...
TylerH

Відповіді:


408

Рішення

Використовуйте вкладені гнучкі контейнери.

Позбавтеся від відсоткової висоти. Позбавтеся від властивостей таблиці. Позбутися vertical-align. Уникайте абсолютного позиціонування. Просто дотримуйтесь флексбоксу весь шлях.

Нанесіть display: flexна гнучкий елемент ( .item), зробивши його гнучким контейнером. Це автоматично встановлюється align-items: stretch, що говорить дитині ( .item-inner) розширити повний зріст батьків.

Важливо: Для цього методу видаліть задані висоти з гнучких елементів. Якщо у дитини вказаний зріст (наприклад height: 100%), то він ігнорує align-items: stretchприхід від батьків. Щоб робота за stretchзамовчуванням працювала, зріст дитини повинен обчислюватися auto (повне пояснення ).

Спробуйте це (без змін у HTML):

демонстрація 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.


Чотири рішення

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видалити безплатну націнку.

Ось приклад:

4. Вкладені контейнери Flex (рекомендується)

Позбавтеся від відсоткової висоти. Позбавтеся від властивостей таблиці. Позбутися vertical-align. Уникайте абсолютного позиціонування. Просто дотримуйтесь флексбоксу весь шлях.

Нанесіть display: flexна гнучкий елемент ( .item), зробивши його гнучким контейнером. Це автоматично встановлюється align-items: stretch, що говорить дитині ( .item-inner) розширити повний зріст батьків.

Важливо: Для цього методу видаліть задані висоти з гнучких елементів. Якщо у дитини вказаний зріст (наприклад height: 100%), то він ігнорує align-items: stretchприхід від батьків. Щоб робота за stretchзамовчуванням працювала, зріст дитини повинен обчислюватися auto (повне пояснення ).

Спробуйте це (без змін у HTML):

jsFiddle



лише деяке зауваження, яке взято із посилання на пояснення цього чудового поста - "align-items: stretch" змушує дітей з гнучкими можливостями розширюватись по поперечній осі контейнера - тобто розтягувати дітей на висоту, гнучка ємність повинна мати напрямок як ряд.
littlewhywhat

3
Я можу підтвердити, що найкраще використовувати вкладені гнучкі контейнери. Ми використовували flexbox непослідовно в нашому меню. Замість використання flex: 1 та дисплея: flex на батьківських контейнерах ми використовували висоту: 100% місцями. Все працювало так, як очікувалося після того, як ми замінили відповідні визначення. Дякую @Michael_B за підказку! :)
flocbit

1
@JamesHarrington, CSS з часом зростав і складний ;-)
DerMike

Кожне рішення має бути різною відповіддю. Як я можу таким чином проголосувати за конкретне рішення?
Jp_

14

Рішення: Видалити height: 100%в .item-внутрішньої і додати display: flexв .item

Демо: https://codepen.io/tronghiep92/pen/NvzVoo


Дякую, це мені допомогло. Чи гнучкі діти автоматично натягуються на висоту свого контейнера? Це чому це працює?
Рис Кенні

@ReeceKenney, так, на ваші запитання. Це пояснено у моїй відповіді. Дивіться рішення №4.
Майкл Бенджамін

10

Вказання атрибута flex для контейнера, який працював для мене:

.container {
    flex: 0 0 auto;
}

Це забезпечує встановлення висоти і не росте.


6

Для мобільного Safari Існує виправлення браузера. вам потрібно додати -webkit-box для пристроїв iOS.

Вих.

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%з дочірнього елемента.


2

У мене була аналогічна проблема в iOS 8, 9 і 10, і інформація вище не могла її виправити, проте я знайшов рішення після дня роботи над цим. Зрозуміло, що він працюватиме не для всіх, але в моєму випадку мої предмети були складені в стовпчик і мали 0 висоти, коли він повинен був бути висотою вмісту. Перемикання CSS на рядок та обгортання вирішило проблему. Це працює лише в тому випадку, якщо у вас є один предмет, і вони складені, але оскільки це знадобилося мені на день, щоб знайти це, я подумав, що я повинен поділитися своїм виправленням!

.wrapper {
    flex-direction: column; // <-- Remove this line
    flex-direction: row; // <-- replace it with
    flex-wrap: wrap; // <-- Add wrapping
}

.item {
    width: 100%;
}

0

У мене була схожа помилка, але при використанні фіксованого числа за висотою, а не відсотком. Це також був гнучкий контейнер всередині кузова (який не має заданої висоти). Виявилося, що на Safari чомусь мій контейнер flex мав висоту 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;
}

Сподіваюсь, це допомагає!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.