2.22. CSS3 flexbox

css-flexboxCSS flexbox (Flexible Box Layout Module) — модуль макета гибкого контейнера — представляет собой способ компоновки элементов.

Flexbox состоит из flex-контейнера — родительского контейнера и flex-элементов — дочерних блоков. Дочерние элементы могут выстраиваться в строку или столбик, а оставшееся свободное пространство распределяется между ними различными способами.

Модуль flexbox позволяет решать следующие задачи:

  • Располагать элементы в одном из четырех направлений: слева направо, справа налево, сверху вниз или снизу вверх;
  • Переопределять порядок отображения элементов;
  • Автоматически определять размеры элементов таким образом, чтобы они вписывались в доступное пространство;
  • Решать проблему с горизонтальным и вертикальным центрированием;
  • Переносить элементы внутри контейнера, не допуская их переполнения;
  • Создавать колонки одинаковой высоты;
  • Создавать прижатый к низу страницы подвал сайта.

В основе flexbox лежит идея оси. Flexbox является инструментом двумерной компоновки и использует для работы две оси — горизонтальную (главную ось) и поперечную.

box-model
Рис. 1. Модель flexbox

Что такое flexbox

Поддержка браузерами

IE: 11.0, 10.0 -ms-
Firefox: 28.0, 18.0 -moz-
Chrome: 29.0, 21.0 -webkit-
Safari: 6.1 -webkit-
Opera: 12.1 -webkit-
iOS Safari: 7.0 -webkit-
Opera Mini: 8
Android Browser: 4.4, 4.1 -webkit-
Chrome for Android: 44

1. Свойства flex-контейнера

Flex-контейнер устанавливает новый гибкий контекст форматирования для его содержимого. Flex-контейнер не является блочным контейнером, поэтому для внутренних блоков не работают такие CSS-свойства, как float, clear, vertical-align. Также, на flex-контейнер не оказывают влияние свойства column-, создающие колонки в тексте и псевдоэлементы ::first-line и ::first-letter.

1.1. Свойство display

Модель flexbox-разметки связана с определенным значением CSS-свойства display родительского html-элемента, содержащего внутри себя дочерние блоки. Для управления элементами с помощью этой модели нужно установить свойство display следующим образом:

.flex-container {
display: -webkit-flex; 
display: flex; /*отображает контейнер как блочный элемент*/
}
.flex-container {
 display: -webkit-inline-flex;
 display: inline-flex; /*отображает контейнер как строчный элемент*/
}

После установки данных значений свойства каждый дочерний элемент автоматически становится flex-элементом, выстраиваясь в ряд (вдоль главной оси) колонками одинаковой высоты, равной высоте блока-контейнера. При этом блочные и строчные дочерние элементы ведут себя одинаково, т.е. ширина блоков равна ширине их содержимого с учетом внутренних полей и рамок элемента.

display-flex
Рис. 2. Выравнивание элементов в модели flexbox

Если родительский блок содержит текст или изображения без оберток, они становятся анонимными flex-элементами. Текст выравнивается по верхнему краю блока-контейнера, а высота изображения становится равной высоте блока, т.е. оно деформируется.

1.2. Выравнивание элементов по горизонтали justify-content

Свойство выравнивает flex-элементы по ширине flex-контейнера, распределяя оставшееся свободное пространство, незанятое flex-элементами. Для выравнивания элементов по вертикали используется свойство align-content. Свойство не наследуется.

justify-content
Значения:
flex-start Значение по умолчанию. Flex-элементы позиционируются от начала flex-контейнера.
flex-end Flex-элементы позиционируются относительно правой границы flex-контейнера.
center Flex-элементы выравниваются по центру flex-контейнера.
space-between Flex-элементы выравниваются по главной оси, свободное место между ними распределяется следующим образом: первый блок располагается в начале flex-контейнера, последний блок – в конце, все остальные блоки равномерно распределены в оставшемся пространстве, а свободное пространство равномерно распределяется между элементами.
space-around Flex-элементы выравниваются по главной оси, а свободное место делится поровну, добавляя отступы справа и слева.
initial Устанавливает значение свойства в значение по умолчанию.
inherit Наследует значение свойства от родительского элемента.
justify-content
Рис. 3. Выравнивание элементов и распределение свободного пространства с помощью свойства justify-content

Синтаксис

.flex-container {
display: -webkit-flex; 
-webkit-justify-content: flex-start;
display: flex;
justify-content: flex-start;
}

1.3. Выравнивание элементов по вертикали align-items

Свойство выравнивает flex-элементы, в том числе и анонимные flex-элементы по перпендикулярной оси (по высоте). Не наследуется.

align-items
Значения:
stretch Значение по умолчанию. Flex-элементы растягиваются, занимая все пространство по высоте.
flex-start Flex-элементы выравниваются по левому краю flex-контейнера относительно верхнего края блока-контейнера.
flex-end Flex-элементы выравниваются по левому краю flex-контейнера относительно нижнего края блока-контейнера.
center Flex-элементы выравниваются по центру flex-контейнера.
baseline Flex-элементы выравниваются по базовой линии.
initial Устанавливает значение свойства в значение по умолчанию.
inherit Наследует значение свойства от родительского элемента.
align-items
Рис. 4. Выравнивание элементов в контейнере по вертикали

Синтаксис

.flex-container {
display: -webkit-flex;
-webkit-align-items: flex-start;
display: flex;
align-items: flex-start;
}

1.4. Направление главной оси flex-direction

Свойство определяет, каким образом flex-элементы укладываются во flex-контейнере, задавая направление главной оси flex-контейнера. Они могут располагаться в двух главных направлениях — горизонтально, как строки или вертикально, как колонки. Главная ось по умолчанию идет слева направо. Поперечная – сверху вниз. Свойство не наследуется.

flex-direction
Значения:
row Значение по умолчанию, слева направо (в rtl справа налево). Flex-элементы выкладываются в строку. Начало (main-start) и конец (main-end) направления главной оси соответствуют началу (inline-start) и концу (inline-end) инлайн оси (inline-axis).
row-reverse Направление справа налево (в rtl слева направо). Flex-элементы выкладываются в строку относительно правого края контейнера (в rtl — левого).
column Направление сверху вниз. Flex-элементы выкладываются в колонку.
column-reverse Колонка с элементами в обратном порядке, снизу вверх.
initial Устанавливает значение свойства в значение по умолчанию.
inherit Наследует значение свойства от родительского элемента.
flex-direction
Рис. 5. Свойство flex-direction для блочных и строчных элементов

Синтаксис

.flex-container {
display: -webkit-flex; 
-webkit-flex-direction: row-reverse;
display: flex;
flex-direction: row-reverse;
}

1.5. Многострочность элементов flex-wrap

Свойство управляет тем, как flex-контейнер будет выкладывать flex-элементы — в одну строку или в несколько, и направлением, в котором будут укладываться новые строки. По умолчанию flex-элементы укладываются в одну строку. При переполнении контейнера их содержимое будет выходить за границы flex-элементов. Не наследуется.

flex-wrap
Значения:
nowrap Значение по умолчанию. Flex-элементы не переносятся, а располагаются в одну линию слева направо (в rtl справа налево).
wrap Flex-элементы переносятся, располагаясь в несколько горизонтальных рядов (если не помещаются в один ряд) в направлении слева направо (в rtl справа налево).
wrap-reverse Flex-элементы переносятся, располагаясь в обратном порядке слева-направо, при этом перенос происходит снизу вверх.
initial Устанавливает значение свойства в значение по умолчанию.
inherit Наследует значение свойства от родительского элемента.
flex-wrap
Рис. 6. Управление многострочностью с помощью свойства flex-wrap

Синтаксис

.flex-container {
display: -webkit-flex; 
-webkit-flex-wrap: wrap;
display: flex;
flex-wrap: wrap;
}

1.6. Краткая запись направления и многострочности flex-flow

Свойство предоставляет возможность в одном свойстве задать направление главной оси и многострочность поперечной оси, т.е. сокращённая запись свойств flex-direction и flex-wrap. Значение по умолчанию flex-flow: row nowrap;. Не наследуется.

flex-flow
Значения:
направление Указывает направление главной оси. Значение по умолчанию row.
многострочность Задаёт многострочность поперечной оси. Значение по умолчанию nowrap.
initial Устанавливает значение свойства в значение по умолчанию.
inherit Наследует значение свойства от родительского элемента.

Синтаксис

.flex-container {
display: -webkit-flex; 
-webkit-flex-flow: row wrap; 
display: flex;
flex-flow: row wrap;
}

1.7. Многострочное выравнивание align-content

Свойство выравнивает строки flex-элементов по вертикали во flex-контейнере, позволяя управлять свободным пространством.
Свойство работает только в случае, если разрешен перенос строк и указано направление flex-flow: row/row-reverse/column/column-reverse wrap/wrap-reverse; и высота flex-контейнера. Не наследуется.

align-content
Значения:
stretch Значение по умолчанию. Строки flex-элементов равномерно растягиваются, заполняя все доступное пространство.
flex-start Строки flex-элементов выравниваются по левому краю flex-контейнера относительно верхнего края блока-контейнера.
flex-end Строки flex-элементов выравниваются по левому краю flex-контейнера относительно нижнего края блока-контейнера.
center Строки flex-элементов выравниваются по высоте по середине flex-контейнера относительно его левого края.
space-between Строки flex-элементов выравниваются по высоте по середине flex-контейнера относительно его левого края. Свободное пространство распределяется между ними. Первый ряд flex-элементов прижимается к началу flex-контейнера, последний ряд — к нижнему краю.
space-around Строки flex-элементов равномерно распределяются по высоте, свободное пространство добавляется сверху и снизу строки.
initial Устанавливает значение свойства в значение по умолчанию.
inherit Наследует значение свойства от родительского элемента.
align-content
Рис. 7. Многострочное выравнивание flex-элементов

Синтаксис

.flex-container {
display: -webkit-flex;
-webkit-flex-flow: row wrap;
-webkit-align-content: flex-end; 
display: flex;
flex-flow: row wrap;
align-content: flex-end;
height: 100px;
}

2. Свойства flex-элементов

2.1. Порядок отображения элементов order

Свойство определяет порядок, в котором flex-элементы отображаются внутри flex-контейнера. По умолчанию для всех flex-элементов задан порядок order: 0; и они следуют друг за другом по мере добавления во flex-контейнер. Самый первый flex-элемент по умолчанию расположен слева. Чтобы поставить любой flex-элемент в начало строки, ему нужно назначить order: -1;, в конец строки — order: 1;. Свойство не наследуется.

order
Значения:
число Свойство задается целым числом, отвечающим за порядок отображения flex-элементов. Значение по умолчанию 0.
initial Устанавливает значение свойства в значение по умолчанию.
inherit Наследует значение свойства от родительского элемента.

Синтаксис

.flex-container {
display: -webkit-flex;
display: flex;
}
.flex-item {
-webkit-order: 1;
order: 1;
}
order
Рис. 8. Порядок отображения flex-элементов

2.2. Базовая ширина элемента flex-basis

Свойство позволяет задать базовую ширину flex-элемента, относительно которой будет происходить растяжение flex-grow или сужение flex-shrink элемента. Не наследуется.

flex-basis
Значения:
auto Значение по умолчанию. Элемент получает базовую ширину, соответствующую ширине контента внутри него, если она не задана явно.
число Ширина элемента задается в px, %, em и других единицах измерения.
initial Устанавливает значение свойства в значение по умолчанию.
inherit Наследует значение свойства от родительского элемента.

Синтаксис

.flex-container {
display: -webkit-flex;
display: flex;
}
.flex-item {
-webkit-flex-basis: 100px; 
flex-basis: 100px;
}

2.3. Растяжение элементов flex-grow

Свойство определяет коэффициент увеличения ширины flex-элемента относительно других flex-элементов. Свойство не наследуется.

flex-grow
Значения:
число Положительное целое или дробное число, устанавливающее коэффициент увеличения flex-элемента. Значение по умолчанию 0.
initial Устанавливает значение свойства в значение по умолчанию.
inherit Наследует значение свойства от родительского элемента.
flex-grow
Рис. 10. Растяжение flex-элементов в строке

Синтаксис

.flex-container {
display: -webkit-flex;
display: flex;
}
.flex-item {
-webkit-flex-grow: 3; 
flex-grow: 3;
}

2.4. Сужение элементов flex-shrink

Свойство указывает коэффициент уменьшения ширины flex-элемента относительно других flex-элементов. Работает только если для элемента задана ширина с помощью свойства flex-basis или width. Свойство не наследуется.

flex-shrink
Значения:
число Положительное целое или дробное число, устанавливающее коэффициент уменьшения flex-элемента. Значение по умолчанию 1.
initial Устанавливает значение свойства в значение по умолчанию.
inherit Наследует значение свойства от родительского элемента.
flex-shrink
Рис. 11. Сужение flex-элементов в строке

Синтаксис

.flex-container {
display: -webkit-flex;
display: flex;
}
.flex-item {
-webkit-flex-shrink: 3; 
flex-shrink: 3;
}

2.5. Задание базовой ширины и трансформации элемента одним свойством flex

Свойство представляет собой сокращённую запись свойств flex-grow, flex-shrink и flex-basis. Значение по умолчанию: flex: 0 1 auto;. Можно указывать как одно, так и все три значения свойств. Свойство не наследуется.

W3C рекомендует использовать сокращённую запись, так как она правильно сбрасывает любые неуказанные компоненты, чтобы подстроиться под типичное использование.

flex
Значения:
коэффициент растяжения Коэффициент увеличения ширины flex-элемента относительно других flex-элементов.
коэффициент сужения Коэффициент уменьшения ширины flex-элемента относительно других flex-элементов.
базовая ширина Базовая ширина flex-элемента.
auto Эквивалентно flex: 1 1 auto;.
none Эквивалентно flex: 0 0 auto;.
initial Устанавливает значение свойства в значение по умолчанию.
inherit Наследует значение свойства от родительского элемента.

Синтаксис

.flex-container {
display: -webkit-flex;
display: flex;
}
.flex-item {
-webkit-flex: 3 1 100px; 
-ms-flex:  3 1 100px; 
flex:  3 1 100px;
}

2.6. Выравнивание отдельных элементов align-self

Свойство отвечает за выравнивание отдельно взятого flex-элемента по высоте flex-контейнера. Переопределяет выравнивание, заданное align-items. Не наследуется.

align-self
Значения:
auto Значение по умолчанию. Flex-элемент использует выравнивание, указанное в свойстве align-items flex-контейнера.
flex-start Flex-элемент выравнивается по верхнему краю flex-контейнера, относительно левой границы.
flex-end Flex-элемент выравнивается по нижнему краю flex-контейнера, относительно левой границы.
center Flex-элемент выравнивается по высоте по середине flex-контейнера, относительно левой границы.
baseline Flex-элемент выравнивается по базовой линии flex-контейнера, относительно левой границы.
stretch Flex-элемент растягивается на всю высоту flex-контейнера, при этом учитываются поля и отступы.
initial Устанавливает значение свойства в значение по умолчанию.
inherit Наследует значение свойства от родительского элемента.
align-self
Рис. 12. Выравнивание отдельных flex-элементов

Синтаксис

.flex-container {
display: -webkit-flex;
display: flex;
}
.flex-item {
-webkit-align-self: center; 
align-self: center;
}
  • Dante

    Спасибо большое за подробное руководство по Flexbox, технология очень мощная и в тоже время гибкая но ее поддерживает IE 10+ с другими браузерами все супер. Есть ли какие нибудь JS библиотеки которые помогут IE 9 и более поздним версиям понять это свойство Flexbox?

    • Универсального скрипта нет. По статистике IE8 — 1.38%, IE9 — 1.1% (используется в мире), может и не стоит заморачиваться?)
      Вариант для IE9 можно посмотреть здесь http://codepen.io/philhoyt/pen/qbzhJ.
      Также можно задать для контейнера:
      .container {
      display: table-cell; // ie9
      display: flex; // остальные браузеры (не забудьте про префиксы)
      }
      Тестирование в разных версиях IE здесь https://dev.modern.ie/tools/screenshots/
      Кроссбраузерная поддержка модели здесь http://flexiejs.com

      • Создание Сайтов

        Хотелось бы понять, какую выгоду можно получить с такого сайта. Неужели это чисто хобби?

    • Создание Сайтов

      Пора бы забыть про эти браузеры. HTML5 приговорила IE. Разработчики посчитали, что проще отказаться от этого браузера, чем переделывать его под HTML5 и CSS3. Да и вообще, если пользователь приходит на мой сайт с такого браузера, то это его проблема, а не моя. Все эти костыли для ИЕ — это мертвому припарка. На одних версиях ОС он работает с примочками, а на других нет. Так что, надо идти в перед, а не пытаться из-за кого-то мизера портить сайт и свои нервы.

      • Я с вами согласна, но нельзя забывать, что это — логика разработчика, а кроме нее существует требование заказчика или руководства о совместимости с IE ранних версий.

        • Создание Сайтов

          Я избегаю таких заказчиков. У кого есть время экспериминтировать с ие, пусть ищет таких заказчиков.

  • Alexandr Bokhonov

    Огромное спасибо за расклад!!!
    Ошибку исправьте на странице: «Чтобы поставить поставить любой flex-элемент в начало…» Слово ПОСТАВИТЬ два раза написано. Помоему, достаточно и одного))

  • Artem Retunsky

    Привет! Спасибо за информацию! Хочу попросить вас еще про гриды написать такое же подробное руководство:)

  • Kate

    Помогите пожалуйста.. делаю display: inline-flex; flex-flow: row wrap; justify-content: space-between;
    но блоки не распределяются в оставшемся пространстве((( Подскажите как правильно сделать?

    • Для блока контейнера задаём:
      {display: -webkit-flex;
      display: flex;
      -webkit-justify-content: space-between;
      justify-content: space-between;
      -webkit-flex-flow: row wrap;
      flex-flow: row wrap;}

      Для дочерних элементов:
      {display: inline-flex;}

      То есть у вас не получилось растянуть, потому что вы объединили в одном объявлении стиля свойства flex-контейнера и flex-элементов.

  • Елена, подскажите пожалуйста. Имеется резиновый сайт интернет-магазина, товары в магазине я выравниваю по гризонтали с помощью флексбокса, задав им justify-content:space-around. Проблема в том, что когда в последней строке остается, например, один товар, то он выравнивается по середине контейнера, а мне нужно, чтоб он выравнивался по левому краю. Другими словами, мне нужно получить такое же выравнивание товаров, как если бы мы задали им display:inline-block, только чтоб товары занимали всю свободную ширину контейнера. Спасибо!

    • http://codepen.io/html5book/pen/qNzwdE
      Посмотрите разницу между первым и вторым способом. С помощью флексбокса эту проблему не решить.

      • Спасибо за ответ!

        • Пожалуйста! Я видела много шаблонов интернет-магазинов, но ни в одном из них не использовался флексбокс для сетки. Только ширина в % и медиазапросы.

    • Александр Абрамов

      Есть способ!)

      я создаю пустые блоки (если макс количество блоков в строке 4 то 4 пустых)

      .empty{
      display: block;
      margin: 0 !important;
      overflow: hidden;
      height: 0 !important;
      }

      а все остальное как у видимых блоков и тогда при любом размере они будут прижимать последний блок

    • Виктор Паланский

      а почему justify-content: flex-start не подойдет?

  • спасибо за подсказку, порядок свойств поменяла.

  • Vasiliy Pereverzev

    может кто подскажет, есть четыре столбца, разной высоты (контент адаптивный, так что вынести нижний ряд в отдельный див не выйдет)
    выглядит примерно так
    — — — —
    — — — —
    — —

    — — — — нужно чтобы этот ряд был на одинаковый высоте и привязанный к нижнему краю и при этом внутри столбца. Высота столбцов может меняться.
    Обернул это все в флекс, чтобы тянуло столбцы на одинаковую высоту. Каждый столбец тоже сдала флекс(column). Для последнего ряда задаю, align-self: flex-end; (baseline или еще что то) ему по барабану. может кто подскажет…

    пока писал нагуглил.
    для последней строки margin-top: auto;

  • Chernov Vladimir

    Спасибо, Елена! Статья очень помогла!)

  • Дмитрий Калюжный

    читал на хабре, так там не наглядно и непонятно. тут все отлично изложено! Спасибо автору! отличная статья!

  • Иван

    Классная документация. Сохранил себе в закладках. Пользуюсь как справкой. Только использую Flex очень редко, потому что IE-9 не воспринимает его.

  • Здравствуйте. Ожидается, пока сдерживает поддержка браузерами.

  • MaxWall

    в последних проектах отказался полностью от флоатов, дисплей-тэйбл, и инлайн-блочного позиционирования. Сделал на флексбоксах и колумнах — норм, всё устойчиво.
    А эту статью положил в закладки — как справочник если что-то подзабыл.
    ———
    Автору спасибо! )
    Просьба есть:
    в разделе «1.7. Многострочное выравнивание align-content» вынести первым значение по умолчанию в табличке. Да и вообще — чтобы по табличкам умолчание шло строго первым.

    • Да, хорошо, переделаю. Также планирую дополнить спецификацию примерами.

  • Voronin David

    Елена добрый день. Столкнулся с таким вопросом, что flex по высоте выравнивает свои элементы только построчно. В примере на кодпене видно, что по высоте выравниваются блоки только нижней строки. Есть какая-либо возможность, чтобы flex выравнивал все колонки под одну высоту, если они находятся на разных строках ? https://codepen.io/brezze/pen/ayvKEb

    • Добрый день. Средствами флексбокс — нет, разве что не установить минимальную высоту вручную https://codepen.io/html5book/pen/gxwKmN.
      Высота каждого ряда ориентируется на содержимое блоков и устанавливается как минимально достаточная, чтобы уместить их по высоте.

  • qwerty

    «Свойство управляет тем, как flex-контейнер будет выкладывать
    flex-элементы — в одну строку или в несколько, и направлением, в котором
    будут укладываться новые строки. По умолчанию flex-элементы
    укладываются в одну строку. При переполнении контейнера их содержимое
    будет выходить за границы flex-элементов. Не наследуется.»
    Вероятно я чего-то не понял, но у меня контейнер не переполняется, flex-itemы просто уменьшаются в ширине.

  • ScorpioT1000

    Реально полезно и очень быстро, на ходу багу зафиксил) спасибо

  • Maxxi

    Спасибо за статью.
    Подскажите, как сделать так, чтобы один из flex-элементов растягивался на всю высоту контейнера, но не увеличивал его размер при выходе контента за рамки, а чтобы у этого элемента появлялся вертикальный скроллер. Т.е. есть два элемента. Один задает высоту контейнера, а второй подстраивается под первый и при необходимости использует прокрутку.

    • Пожалуйста. Не думаю, что средствами флексбокс такое можно сделать. Если макет страницы фиксированной ширины, то можно зафиксировать высоту элемента со скроллом, например, {height: 200px; overflow-y:scroll}. Для резиновой верстки этот способ не подойдет, потому что высота будет меняться динамически, следовательно, ее значение нужно будет сохранять в переменной, а это уже скрипт, а не стили.