Браузерные баги Flexbox

Перевод материала из github-репозитория Flexbugs с разрешения его владельца — Филипа Уолтона.

Этот репозиторий — поддерживаемый сообществом список проблем с flexbox и кроссбраузерных обходных путей для них. Цель такова, что если вы разрабатываете сайт, используя 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. Элементы <button> не могут быть flex-контейнерами
  10. align-items: baseline не работает с вложенными flex-контейнерами
  11. Объявления минимального и максимального размера не учитываются при переносе флекс-элементов
  12. Строчные элементы не становятся флекс-элементами

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% (или 100vh). Поскольку элемент 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 0px всё ещё может вызвать проблемы, поскольку многие CSS-минимизаторы конвертируют 0px в 0. Чтобы этого избежать, не забывайте использовать 0% вместо 0px, т.к большинство минимизаторов не трогают процентные значения по другим причинам.

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.abug
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% переполняет свой контейнер на величину равную его границе + внутренний отступ.

Обходной путь

Есть два способа обойти этот баг. Первый не требует дополнительной разметки, но второй немного более гибкий:

  1. Вместо установки явного значения basis,  используйте auto, а затем установите явную ширину или высоту. Это показано в демо-примере 7.1.b.
  2. Используйте элемент-обертку без границ и отступов, чтобы он работал по модели 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. Это тоже может быть интересно:

12 Комментарии

  1. Николай

    Скорее не баг, а недоработка.
    В общем захожу я такой в спеку
    Кручу в самый низ, а там табличка про все свойства. Нахожу там, что order можно анимировать. Думаю — нифига себе надо попробовать. Час просидел в codepen, и что вы думаете Chrome не умеет анимировать order =)
    Вот пруф Codepen
    Firefox справился с этой задачей. Префиксы не помогают.

    1. SelenIT

      Вполне себе баг (раз по спеке должно быть можно)! Надо добавить issue в репозиторий Филипу и написать в багтрекер Хрома. Спасибо!

  2. nerzh

    Ребята, такой важный вопрос: есть контейнер, а внутри содержимое. Всё сделано на flex … Проблема в следующем, когда содержимое выростает за пределы экрана, то наверно так как стоит горизонтальное выравнивание по центру результат следующий, я могу проскролить в самый низ и до этой середины документа, всё что выше уходит за верхний предел экрана и его не увидеть никак, тоесть другими словами как бы верхняя граница становится не там где верхняя часть контейнера, а гораздо ниже и скролла вверх нет, тоесть могу увидеть самый низ документа и до определённого момента остальную часть, самый верх скрывается и туда не скролится…

    1. nerzh

      п.с. не горизонтальное, а вертикальное выравнивание …

      1. SelenIT

        В смысле justify-content:center при flex-direction: column? Тоже с таким сталкивался, но это не баг браузеров, а особенность стандарта. Я пока смог придумать только такой обходной путь.

        Или речь про что-то другое (пример бы не помешал)?

        1. nerzh

          да, по анимации проблема похожа, сейчас попробую понять решение и применить его, хочу сказать, что я подозревал, что это не баг, а отсутствие опыта, я вообще никогда не верстал и начал сразу с flex так как вижу, что новые версии всех браузеров поддержали новую тенденцию flexbox и считаю, что скоро они просто обязаны полностью заменить все алогичные и бредовые решения в вёрстке ) Во всяком случае надеюсь на это, с flex вёрстка превращается в логичное строение блоков, которое, за исключением подобных нюансов, мне стало понятно в течении часа и я уже смог сверстать первую страницу и самое главное имел в голове примерную картину как это сделать из этих блоков. Дофига написал не по теме багов, просто накипело) Знакомые верстальщики пока скептически относятся к этому flexbox — у из-за поддержки браузеров и особенно наверно потому, что они потратили не один год, чтобы накопить решения типа банального вертикального выравнивания, но будет вам уникальный текст

          1. SelenIT

            То ли еще будет, когда Grid Layout пойдет в массы! Есть надежда, что довольно скоро. Там, кажется, вообще ограничений не будет:). На мой взгляд, уже есть смысл присматриваться к нему (у нас как раз недавно несколько статей про него вышли:).

            1. nerzh

              Прочитал, очень-очень заманчиво, но никто из «webkit» его ещё не поддержал пока, видимо он совсем свеженький ? http://caniuse.com/#search=grid%20layout

              1. SelenIT

                Хром достаточно давно поддерживает за флагом. Ходят слухи, что флаг могут убрать уже этой осенью:)

                1. nerzh

                  специально для решения проблемы выложил в сеть. Чтобы увидеть БАГ, нужно зарегаться, почта пока не валидируется, поэтому можете использовать хоть w@w.w пароль от 8 знаков, никаких писем, ничего… И всё, потом понажимайте несколько раз кнопку ADD ToDoList, чтобы заполнить вертикально страницу и вы увидете, то о чём я говорил из-за того, что у основного блока html стоит display: flex и он height: 100% все остальные внутри него и могут выравниваться по центру благодаря justify-content: center;. НО, как вы увидете при заполнении страницы контентом, он выравнивает его и скрывает верхнюю часть за пределами видимости и не скролит туда. Поможете мне с этим ? вот ссылка http://todolist.inclouds.com.ua

                  1. SelenIT

                    Да, похоже, что в данном случае это именно баг, и именно с динамикой, потому что после обновления страницы всё становится на место. Возможно, дело в многократной вложенности флексбоксов разного направления, вынуждающей браузер слишком много всего пересчитывать при изменении размеров внутренней области. Нужно сделать минимальный пример, чтоб с ним можно было пойти жаловаться в багтрекеры браузеров (попытаюсь сам на досуге, но если сделаете раньше — весь веб скажет спасибо:).

                2. nerzh

                  зашел под вашим w@w.w посмотрел, всё таки нет всё статично а не динамично, то просто оно так центрирует, что кажется норм, а на самом деле в верху должна быть надпись sing_out, а её нет, вы до неё доберётесь только если поудаляете листы, которые её туда подпирают, так что после перезагрузки страницы всё так же… может это нормальное поведение flex, просто у меня тогда вопрос, как всё таки отцентровать контент по вертикали именно всей страницы, потому как

                  !Если самому наружному блоку я не даю высоту 100%, то он по умолчанию тонкий и внутренние блоки не становятся по центру экрана, а если я наружному дам всё-таки высоту 100%, естественно внутренние центруются относительно него, но происходит эта чихарда со скроллом и скрытым контентов в результате этого центрирования. Получается, что центровать по вертикали вроде можно, но основной блок — по центру экрана нельзя, иначе при увеличении контента — сами видели что будет :-(

Оставить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Получать новые комментарии по электронной почте. Вы можете подписаться без комментирования.