Браузерные баги Flexbox
Перевод материала из github-репозитория Flexbugs с разрешения его владельца — Филипа Уолтона.
Этот репозиторий — поддерживаемый сообществом список проблем с flexbox и кроссбраузерных обходных путей для них. Цель такова, что если вы разрабатываете сайт, используя flexbox, и при этом что-то работает не так, как вы ожидали, то здесь вы можете найти решение.
Пока спецификация продолжает развиваться и браузеры уточняют свои реализации, этот репозиторий будет обновляться свежеобнаруженными проблемами и удалять старые по мере их решения или устаревания. Если вы обнаружили баг, которого нет в этом списке, пожалуйста сообщите о нём, чтобы была польза для всех.
Баги и их обходные пути
- Минимальный размер по контенту flex-элементов не учитывается
- Flex-элементы столбца, которым установлено
align-items:center
, переполняют свой контейнер Min-height
для flex-контейнера столбца не применяется к его flex-элементам- Сокращенная запись
flex
с безразмерными значениямиflex-basis
игнорируется - Flex-элементы столбца не всегда сохраняют внутренние пропорции
- Значение
flex
по умолчанию изменилось Flex-basis
не учитываетbox-sizing:border-box
Flex-basis
не поддерживаетcalc()
- Элементы <button> не могут быть flex-контейнерами
align-items: baseline
не работает с вложенными flex-контейнерами- Объявления минимального и максимального размера не учитываются при переносе флекс-элементов
- Строчные элементы не становятся флекс-элементами
1. Минимальный размер по контенту flex-элементов не учитывается
Демо | В каких браузерах проявляется | Ссылки на баги |
---|---|---|
1.1.a — баг 1.1.b — обходной путь 1.2.a — баг 1.2.b — обходной путь |
Chrome Opera Safari |
Chrome #426898 Firefox #1043520 |
Когда flex-элементы слишком велики, чтобы уместиться в свой контейнер то алгоритм flex-раскладки предписывает этим элементам пропорционально уменьшаться, в соответствии с их свойством flex-shrink. Но вопреки тому, что позволяет большинство браузеров, им не предполагается уменьшаться неограниченно. Они не должны становиться меньше, чем указывают их свойства минимальной высоты и ширины, а если эти свойства не заданы, то их минимальным размером должен быть минимальный размер их содержимого по умолчанию.
В соответствии с текущей спецификацией flexbox:
По умолчанию, flex-элементы не будут уменьшаться сверх минимального размера их содержимого (длина самого длинного слова или элемента с фиксированным размером). Чтобы это изменить, установите свойство min-width или min-height.
Обходной путь
Спецификация flexbox определяет начальное значение flex-shrink
как «1
», но говорит, что элементы не должны быть меньше их минимального размера содержимого по умолчанию. Можно добиться практически точно такого же поведения, используя значение 0
для flex-shrink вместо 1
по умолчанию. Если элемент уже принимает размер по содержимому, и ему не заданы значения width
, height
или flex-basis
, то при установке flex-shrink
:0
он отобразится точно так же — но избежит этого бага.
2. Flex-элементы столбца, которым установлено align-items:center
, переполняют свой контейнер.
Демо | В каких браузерах проявляется |
---|---|
2.1.a — баг 2.1.b — обходной путь |
Internet Explorer 10-11 (исправлено в 12+) |
При использовании align-items
:
center
для вертикального flex-контейнера содержимое flex-элемента, если оно слишком велико, будет переполнять свой контейнер в IE 10-11.
Чаще всего это можно исправить путём простой установки max-width
:100%
для flex-элемента. Если у flex-элемента установлен внутренний отступ или граница, то тогда для учета этой области нужно обязательно применить box-sizing
:
border-box
.
Если flex-элементу выставлен внешний отступ, то одно лишь box-sizing
не сработает, поэтому вместо этого вам понадобится контейнер с внутренним отступом.
3. Min-height
для flex-контейнера столбца не применяется к его flex-элементам
Демо | В каких браузерах проявляется | Ссылки на баги |
---|---|---|
3.1.a — баг 3.1.b — обходной путь 3.2.a — баг |
Internet Explorer 10-11 (исправлено в 12+) | IE #802625 |
Чтобы flex-элементы могли определить свой размер и положение, им необходимо знать размер своего контейнера. Например, если предполагается вертикально отцентрировать flex-элемент, ему необходимо знать высоту своего родительского элемента. Также это относится и к flex-элементам, которым указано, чтобы они растянулись на всё оставшееся место.
В IE 10-11 объявления min-height
для вертикальных flex-контейнеров служат для определения размера самих контейнеров, но их дочерний flex-элемент, похоже, не знает размер своих родительских элементов. Контейнеры ведут себя так, как если бы для них всех не была установлена высота.
Обходной путь
Сейчас min-height
чаще всего устанавливают элементу body, обычно со значением 100%
(или 100
vh
). Поскольку элемент body никогда не будет иметь содержимого после себя, а появление полосы прокрутки при большом объёме контента, обычно, желательное поведение, то замена min-height
на height
будет почти всегда работать, как показано в демо-примере 3.1.b.
Однако, существуют случаи, когда нет хорошего обходного пути. В демо-примере 3.2.a показан визуальный дизайн, когда применение min-height
оправдано необходимо, а замена на height
не работает. В таких случаях, вам, возможно, нужно пересмотреть свой дизайн, или прибегнуть к хаку с определением браузера.
4. Сокращенная запись flex
с безразмерными значениями flex-basis
игнорируется.
Демо | В каких браузерах проявляется |
---|---|
3.1.a — баг 3.1.b — обходной путь |
Internet Explorer 10-11 (исправлено в 12+) |
До выхода IE10 спецификация flexbox заявляла, что при использовании сокращённой записи flex
для предпочтительного размера flexbox-элементов требуется единица измерения:
Если <предпочтительным размером> является «0», то, чтобы избежать двусмысленности, он должен быть указан с единицей измерения (напр. «0px»); безразмерный ноль будет интерпретироваться как
flex-grow
илиflex-shrink
, либо как синтактическая ошибка.
В спецификации это уже не так, но IE 10-11 всё ещё принимают это за правду. Если вы используете объявление flex
: 1 0 0
в одном из этих браузеров, это будет ошибкой и целое правило (включая любые свойства flex’oв) будет проигнорировано.
Обходной путь
При использовании сокращённой записи flex
, всегда включайте единицы измерения в часть flex-basis
. Например: 1 0 0%
.
Важно: использование значения flex
наподобие 1 0 0
px
всё ещё может вызвать проблемы, поскольку многие CSS-минимизаторы конвертируют 0
px
в 0
. Чтобы этого избежать, не забывайте использовать 0%
вместо 0
px
, т.к большинство минимизаторов не трогают процентные значения по другим причинам.
5. Flex-элементы столбца не всегда сохраняют внутренние пропорции.
Демо | В каких браузерах проявляется |
---|---|
5.1.a — баг 5.1.b — обходной путь |
Internet Explorer 10-11 (исправлено в 12+) |
Вот что говорит спецификация на март 2014 о том, как определяются размеры для flex-элементов:
Для Flex-элемента, у которого overflow не равно visible, это ключевое слово [auto] указывает в качестве минимального размера наименьшее из следующего: (а) размер по минимальному содержимому, б) вычисленная ширина/высота, если это значение определенное.
Демо-пример 5.1.a содержит изображение, высота которого составляет 200, а ширина 500 пикселей. Однако, его контейнер имеет ширину всего 300 пикселей, таким образом, когда изображение масштабируется, чтобы уместиться в эту область, его вычисленная высота должна быть только 120 пикселей. Приведённый выше текст в цитате не позволяет чётко понять, на чём должен быть основан размер flex-элемента по минимальному содержимому, на реальной или на отмасштабированной высоте изображения.
Новейшая спецификация решила эту двусмысленность в пользу использования тех размеров, которые позволят сохранить пропорции.
Обходной путь
Можно избежать этой проблемы путём добавления контейнера для элемента, чтобы разместить элемент с внутренней пропорцией. Поскольку это действие приводит к тому, что элемент с внутренними пропорциями больше не будет flex-элементом, он будет подбирать размер обычным способом.
6. Значение flex
по умолчанию изменилось
Демо | В каких браузерах проявляется |
---|---|
6.1.a — баг 6.1.b — обходной путь |
Internet Explorer 10 (исправлено в 11+) |
Когда IE10 разрабатывался, спецификация от марта 2012 говорила, что исходное значение для свойства flex
было none
, которое преобразовывается в 0 0
auto
. Новейшая спецификация устанавливает исходное значение flex
в исходные значения его отдельных составляющих, которые соответствуют initial
или 0 1
auto
. Заметьте, что это означает, что IE 10 использует разное исходное значение flex-shrink
(на тот момент это называлось neg-flex
в спецификации) в отличие от любого другого браузера. Другие браузеры (включая IE 11) используют исходное значение 1
вместо 0
.
Обходной путь
Если вам требуется поддержка IE 10, самым лучшим решением будет всегда явно устанавливать значение flex-shrink
или flex
для всех flex-элементов. Демо-пример 6.1.a показывает, как неуказание любой из составляющих свойства flex приводит к ошибке.
7. Flex-basis
не учитывает box-sizing:border-box
Демо | В каких браузерах проявляется |
---|---|
7.1.a — bug 7.1.b — обходной путь 7.1.c — обходной путь |
Internet Explorer 10-11 (исправлено в 12+) |
Явное значение flex-basis
(т.е. любое значение кроме auto
) должно действовать так же, как width
или height
. Оно определяет исходный размер flex-элемента, и тогда другие свойства flexbox’ов позволяют ему растягиваться или сужаться соответственно.
IE 10-11 всегда предполагает модель content-box при использовании flex-basis
для определения размера flex-элемента, даже, если этот элемент устанавливается в box-sizing
:
border-box
. Демо-пример 7.1.a показывает, что элемент с flex-basis
в 100%
переполняет свой контейнер на величину равную его границе + внутренний отступ.
Обходной путь
Есть два способа обойти этот баг. Первый не требует дополнительной разметки, но второй немного более гибкий:
- Вместо установки явного значения
basis
, используйтеauto
, а затем установите явную ширину или высоту. Это показано в демо-примере 7.1.b. - Используйте элемент-обертку без границ и отступов, чтобы он работал по модели content-box. Это показано в демо-примере 7.1.c.
8. flex-basis
не поддерживает calc()
Демо | В каких браузерах проявляется |
---|---|
8.1.a — баг 8.1.b — обходной путь |
Internet Explorer 10-11 (исправлено в 12+) |
8.2.a — баг 8.2.b — обходной путь |
Internet Explorer 10 (исправлено в 11+) |
IE 10-11 игнорирует функции calc()
в сокращённом объявлении flex
. В демо-примере видно, что flex
:0 0
calc(100%/3)
не работает в IE.
В IE 10 функция calc()
не работает даже в развернутом объявлении flex-basis
. (хотя это работает в IE 11+). В демо-примере 8.2.a показано, как flex-basis
: calc(100%/3)
не работает в IE 10.
Обходной путь
Поскольку этот баг влияет только на сокращённое объявление flex
в IE 11, простым обходным путём будет всегда указывать каждую составляющую flex отдельно. Демо-пример 8.1.b предлагает пример этого решения.
Если также нужна поддержка IE 10, тогда вам придется подстраховаться установкой width
или height
(в зависимости от свойства flex-direction
для контейнера). Можно сделать это путём установки свойства flex-basis
в auto
, которое прикажет браузеру использовать свойство главного размера элемента (т.е. его width
или height
). Это показано в демо-примере 8.2.b.
9. Элементы <button>
не могут быть flex-контейнерами
Демо | В каких браузерах проявляется | Ссылки на баги |
---|---|---|
9.1.a — баг 9.1.b — обходной путь |
Firefox | Firefox #984869 |
В отличие от элемента <input>
с типами «button» или «submit», HTML5-элемент <button>
может содержать дочерние элементы. Это позволяет класть внутрь элемента <button>
не только текст, но и другие вещи (напр. иконки) без необходимости прибегать к использованию семантически некорректных тегов, типа <div>
или <a>
. Однако, Firefox не позволяет элементу <button>
быть flex-контейнером.
Обходной путь
Простое решение этой проблемы – использовать обёрточный элемент внутри button и применить к нему display
:
flex
. Затем <button>
может быть оформлен как обычно.
10. align-items: baseline
не работает с вложенными flex-контейнерами
Демо | В каких браузерах проявляется | Ссылки на баги |
---|---|---|
10.1.a — баг 10.1.b — обходной путь |
Firefox | Firefox #1146442 |
В Firefox вложенные flex-контейнеры не влияют на базовую линию, по которой должны выравниваться другие flex-элементы. В демо-примере 10.1.a видно, как строка слева ошибочно выравнивается со второй строкой текста справа. Она должна выравниваться с первой строкой текста, являющейся внутренним flex-контейнером.
Обходной путь
Этот баг влияет только на вложенные контейнеры с display: flex
. Если установить вложенным контейнерам display: inline-flex
, то всё будет работать так, как ожидалось. Заметьте, что при использовании inline-flex
, вам, вероятно, следует установить ширину 100%.
11. Объявления минимального и максимального размера не учитываются при переносе флекс-элементов
Демо | В каких браузерах проявляется | Ссылки на баги |
---|---|---|
11.1.а — баг 11.1.б — обходной путь |
Safari | Safari #136041 |
Safari учитывает ограничения максимального и минимального размера при отрисовке флекс-элементов, но не учитывает их при расчете того, сколько элементов должно быть на одной строке в многострочном флекс-контейнере. Он учитывает только значение flex-basis
элемента, а если оно равно auto
— то его ширину.
Это не дает использовать сокращение flex:1
, потому что при этом flex-basis
становится равен 0%
, а раз браузер считает ширину флекс-элементов нулевой, то в одной строке их поместится неограниченное количество. В примере 11.1.а видно, как это происходит.
Это также затрудняет создание резиновых макетов, в которых флекс-элементы должны быть не больше величины X, но не меньше Y. Поскольку Safari распределяет элементы по строкам без учета максимального/минимального размера, такой план не сработает.
Обходной путь
Единственный способ справиться с этой загвоздкой — задать для flex-basis
такое значение, которое заведомо войдет в диапазон между ограничениями максимального и минимального размера (включительно). Если задана только максимальная или минимальная граница размера, задайте это же значение для flex-basis
, если заданы обе, значение flex-basis
должно быть где-то в этих пределах. Чтобы учесть все возможные ситуации, может понадобиться задать это значение в процентах или менять его с помощью медиавыражений. В примере 11.1.б можно увидеть, как этот баг Safari обходится заданием одинаковых значений для min-width
и flex-basis
.
12. Строчные элементы не становятся флекс-элементами
Демо | В каких браузерах проявляется |
---|---|
12.1.а — баг 12.1.б — обходной путь |
Internet Explorer 10-11 (исправлено в Edge) |
В IE10 строчные элементы, в т.ч. псевдоэлементы ::before
и ::after
, не становятся флекс-элементами. В IE11 это исправлено для обычных строчных элементов, но для псевдоэлементов ::before
и ::after
баг остался.
Обходной путь
Чтобы избежать этого, достаточно добавить элементам любое значение display
, кроме inline
, напр. block
, inline-block
, flex
и т.п. В примере 12.1.б видно, как это работает в IE10-11.
Благодарности
Браузерные баги были описаны в качестве дополнения к статье «Упорядочивание багов кроссбраузерности Flexbox». Этот документ поддерживается @philwalton и @gregwhitworth. Если у вас есть какие-либо вопросы или вы хотели бы принять участие, пожалуйста не стесняйтесь обращаться к любому из нас в твиттер.
Содействие
Если вы обнаружили баг flexbox или хотели бы предложить обходной путь, пожалуйста откройте «issue» или предложите «pull request». Не забудьте представить соответствующие тестовые примеры или скриншоты и указать, в каких браузерах баг обнаружен.
P.S. Это тоже может быть интересно:
Скорее не баг, а недоработка.
В общем захожу я такой в спеку
Кручу в самый низ, а там табличка про все свойства. Нахожу там, что order можно анимировать. Думаю — нифига себе надо попробовать. Час просидел в codepen, и что вы думаете Chrome не умеет анимировать order =)
Вот пруф Codepen
Firefox справился с этой задачей. Префиксы не помогают.
Вполне себе баг (раз по спеке должно быть можно)! Надо добавить issue в репозиторий Филипу и написать в багтрекер Хрома. Спасибо!
Ребята, такой важный вопрос: есть контейнер, а внутри содержимое. Всё сделано на flex … Проблема в следующем, когда содержимое выростает за пределы экрана, то наверно так как стоит горизонтальное выравнивание по центру результат следующий, я могу проскролить в самый низ и до этой середины документа, всё что выше уходит за верхний предел экрана и его не увидеть никак, тоесть другими словами как бы верхняя граница становится не там где верхняя часть контейнера, а гораздо ниже и скролла вверх нет, тоесть могу увидеть самый низ документа и до определённого момента остальную часть, самый верх скрывается и туда не скролится…
п.с. не горизонтальное, а вертикальное выравнивание …
В смысле
justify-content:center
приflex-direction: column
? Тоже с таким сталкивался, но это не баг браузеров, а особенность стандарта. Я пока смог придумать только такой обходной путь.Или речь про что-то другое (пример бы не помешал)?
да, по анимации проблема похожа, сейчас попробую понять решение и применить его, хочу сказать, что я подозревал, что это не баг, а отсутствие опыта, я вообще никогда не верстал и начал сразу с flex так как вижу, что новые версии всех браузеров поддержали новую тенденцию flexbox и считаю, что скоро они просто обязаны полностью заменить все алогичные и бредовые решения в вёрстке ) Во всяком случае надеюсь на это, с flex вёрстка превращается в логичное строение блоков, которое, за исключением подобных нюансов, мне стало понятно в течении часа и я уже смог сверстать первую страницу и самое главное имел в голове примерную картину как это сделать из этих блоков. Дофига написал не по теме багов, просто накипело) Знакомые верстальщики пока скептически относятся к этому flexbox — у из-за поддержки браузеров и особенно наверно потому, что они потратили не один год, чтобы накопить решения типа банального вертикального выравнивания, но будет вам уникальный текст
То ли еще будет, когда Grid Layout пойдет в массы! Есть надежда, что довольно скоро. Там, кажется, вообще ограничений не будет:). На мой взгляд, уже есть смысл присматриваться к нему (у нас как раз недавно несколько статей про него вышли:).
Прочитал, очень-очень заманчиво, но никто из «webkit» его ещё не поддержал пока, видимо он совсем свеженький ? http://caniuse.com/#search=grid%20layout
Хром достаточно давно поддерживает за флагом. Ходят слухи, что флаг могут убрать уже этой осенью:)
специально для решения проблемы выложил в сеть. Чтобы увидеть БАГ, нужно зарегаться, почта пока не валидируется, поэтому можете использовать хоть w@w.w пароль от 8 знаков, никаких писем, ничего… И всё, потом понажимайте несколько раз кнопку ADD ToDoList, чтобы заполнить вертикально страницу и вы увидете, то о чём я говорил из-за того, что у основного блока html стоит display: flex и он height: 100% все остальные внутри него и могут выравниваться по центру благодаря justify-content: center;. НО, как вы увидете при заполнении страницы контентом, он выравнивает его и скрывает верхнюю часть за пределами видимости и не скролит туда. Поможете мне с этим ? вот ссылка http://todolist.inclouds.com.ua
Да, похоже, что в данном случае это именно баг, и именно с динамикой, потому что после обновления страницы всё становится на место. Возможно, дело в многократной вложенности флексбоксов разного направления, вынуждающей браузер слишком много всего пересчитывать при изменении размеров внутренней области. Нужно сделать минимальный пример, чтоб с ним можно было пойти жаловаться в багтрекеры браузеров (попытаюсь сам на досуге, но если сделаете раньше — весь веб скажет спасибо:).
зашел под вашим w@w.w посмотрел, всё таки нет всё статично а не динамично, то просто оно так центрирует, что кажется норм, а на самом деле в верху должна быть надпись sing_out, а её нет, вы до неё доберётесь только если поудаляете листы, которые её туда подпирают, так что после перезагрузки страницы всё так же… может это нормальное поведение flex, просто у меня тогда вопрос, как всё таки отцентровать контент по вертикали именно всей страницы, потому как
!Если самому наружному блоку я не даю высоту 100%, то он по умолчанию тонкий и внутренние блоки не становятся по центру экрана, а если я наружному дам всё-таки высоту 100%, естественно внутренние центруются относительно него, но происходит эта чихарда со скроллом и скрытым контентов в результате этого центрирования. Получается, что центровать по вертикали вроде можно, но основной блок — по центру экрана нельзя, иначе при увеличении контента — сами видели что будет :-(
Добрый день! Будет ли дополняться статья описаниями новых багов? Столкнулся с багами которые описаны у Филиппа, но нет у Вас
з.ы. Хотел написать в форму обратной связи, но она не работает