- Браузерные баги Flexbox
- Баги и их обходные пути
- 1. Минимальный размер по контенту flex-элементов не учитывается
- Обходной путь
- 2. Flex-элементы столбца, которым установлено align-items:center , переполняют свой контейнер.
- 3. Min-height для flex-контейнера столбца не применяется к его flex-элементам
- Обходной путь
- 4. Сокращенная запись flex с безразмерными значениями flex-basis игнорируется.
- Обходной путь
- 5. Flex-элементы столбца не всегда сохраняют внутренние пропорции.
- Обходной путь
- 6. Значение flex по умолчанию изменилось
- Обходной путь
- 7. Flex-basis не учитывает box-sizing:border-box
- Обходной путь
- 8. flex-basis не поддерживает calc()
- Обходной путь
- 9. Элементы не могут быть flex-контейнерами
- Обходной путь
- 10. align-items: baseline не работает с вложенными flex-контейнерами
- Обходной путь
- 11. Объявления минимального и максимального размера не учитываются при переносе флекс-элементов
- Обходной путь
- 12. Строчные элементы не становятся флекс-элементами
- Обходной путь
- Благодарности
- Содействие
- P.S. Это тоже может быть интересно:
- 13 комментариев
Браузерные баги Flexbox
Перевод материала из github-репозитория Flexbugs с разрешения его владельца — Филипа Уолтона.
Этот репозиторий — поддерживаемый сообществом список проблем с flexbox и кроссбраузерных обходных путей для них. Цель такова, что если вы разрабатываете сайт, используя flexbox, и при этом что-то работает не так, как вы ожидали, то здесь вы можете найти решение.
Пока спецификация продолжает развиваться и браузеры уточняют свои реализации, этот репозиторий будет обновляться свежеобнаруженными проблемами и удалять старые по мере их решения или устаревания. Если вы обнаружили баг, которого нет в этом списке, пожалуйста сообщите о нём, чтобы была польза для всех.
Баги и их обходные пути
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. Но вопреки тому, что позволяет большинство браузеров, им не предполагается уменьшаться неограниченно. Они не должны становиться меньше, чем указывают их свойства минимальной высоты и ширины, а если эти свойства не заданы, то их минимальным размером должен быть минимальный размер их содержимого по умолчанию.
По умолчанию, 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. Элементы не могут быть flex-контейнерами
Демо | В каких браузерах проявляется | Ссылки на баги |
---|---|---|
9.1.a — баг 9.1.b — обходной путь | Firefox | Firefox #984869 |
В отличие от элемента с типами «button» или «submit», HTML5-элемент может содержать дочерние элементы. Это позволяет класть внутрь элемента не только текст, но и другие вещи (напр. иконки) без необходимости прибегать к использованию семантически некорректных тегов, типа
Обходной путь
Простое решение этой проблемы – использовать обёрточный элемент внутри button и применить к нему display : flex . Затем может быть оформлен как обычно.
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.б — обходной путь |