Модуль Flexbox-лейаута (flexible box — «гибкий блок», на данный момент W3C Candidate Recommendation) ставит задачу предложить более эффективный способ вёрстки, выравнивания и распределения свободного места между элементами в контейнере, даже когда их размер неизвестен и/или динамический (отсюда слово «гибкий»).
Главная задумка flex-вёрстки в наделении контейнера способностью изменять ширину/высоту (и порядок) своих элементов для наилучшего заполнения пространства (в большинстве случаев — для поддержки всех видов дисплеев и размеров экранов). Flex-контейнер растягивает элементы для заполнения свободного места или сжимает их, чтобы предотвратить выход за границы.
Самое важное, flexbox-лейаут не зависит от направления в отличие от обычных лейаутов (блоки, располагающиеся вертикально, и инлайн-элементы, располагающиеся горизонтально). В то время, как обычный лейаут отлично подходит для веб-страниц, ему не хватает гибкости (никакого каламбура) для поддержки больших или сложных приложений (особенно когда дело доходит до смены ориентации экрана, изменения размера, растягивания, сжатия и т.п.).
Замечание: Flexbox-лейаут лучше всего подходит для составных частей приложения и мелкомасштабных лейаутов, в то время как Grid-лейаут больше используется для лейаутов большого масштаба.
Основы
Т.к. flexbox — это целый модуль, а не просто единичное свойство, он объединяет в себе множество свойств. Некоторые из них должны применяться к контейнеру (родительскому элементу, так называемому flex-контейнеру), в то время как другие свойства применяются к дочерним элементам, или flex-элементам.
Если обычный лейаут основывается на направлениях потоков блочных и инлайн-элементов, то flex-лейаут основывается на «направлениях flex-потока». Ознакомьтесь с этой схемой из спецификации, разъясняющей основную идею flex-лейаутов.
В основном элементы будут распределяться либо вдоль главной оси (от main-start до main-end), либо вдоль поперечной оси (от cross-start до cross-end).
- main-axis — главная ось, вдоль которой располагаются flex-элементы. Обратите внимание, она необязательно должна быть горизонтальной, всё зависит от свойства
flex-direction
(см. ниже). - main-start | main-end — flex-элементы размещаются в контейнере от позиции main-start до позиции main-end.
- main size — ширина или высота flex-элемента в зависимости от выбранной основной величины. Основная величина может быть либо шириной, либо высотой элемента.
- cross axis — поперечная ось, перпендикулярная к главной. Её направление зависит от направления главной оси.
- cross-start | cross-end — flex-строки заполняются элементами и размещаются в контейнере от позиции
cross-start
и до позицииcross-end
. - cross size — ширина или высота flex-элемента в зависимости от выбранной размерности равняется этой величине. Это свойство совпадает с
width
илиheight
элемента в зависимости от выбранной размерности.
Свойства
display: flex | inline-flex;
Применяется к: родительскому элементу flex-контейнера.
Определяет flex-контейнер (инлайновый или блочный в зависимости от выбранного значения), подключает flex-контекст для всех его непосредственных потомков.
display: other values | flex | inline-flex;
Имейте в виду:
- CSS-столбцы
columns
не работают с flex-контейнером float
,clear
иvertical-align
не работают с flex-элементами
flex-direction
Применяется к: родительскому элементу flex-контейнера.
Устанавливает главную ось main-axis
, определяя тем самым направление для flex-элементов, размещаемых в контейнере.
flex-direction: row | row-reverse | column | column-reverse
row
(по умолчанию): слева направо дляltr
, справа налево дляrtl
;row-reverse
: справа налево дляltr
, слева направо дляrtl
;column
: аналогичноrow
, сверху вниз;column-reverse
: аналогичноrow-reverse
, снизу вверх.
flex-wrap
Применяется к: родительскому элементу flex-контейнера.
Определяет, будет ли контейнер однострочным или многострочным, а также направление поперечной оси, определяющей направление, в котором будут располагаться новые строки.
flex-wrap: nowrap | wrap | wrap-reverse
nowrap
(по умолчанию): однострочный / слева направо дляltr
, справа налево дляrtl
;wrap
: многострочный / слева направо дляltr
, справа налево дляrtl
;wrap-reverse
: многострочный / справа налево дляltr
, слева направо дляrtl
.
flex-flow
Применяется к: родительскому элементу flex-контейнера.
Это сокращение для свойств flex-direction
и flex-wrap
, вместе определяющих главную и поперечную оси. По умолчанию принимает значение row nowrap
.
flex-flow: <'flex-direction'> || <'flex-wrap'>
justify-content
Применяется к: родительскому элементу flex-контейнера.
Определяет выравнивание относительно главной оси. Помогает распределить оставшееся свободное место в случае, когда элементы строки не «тянутся», либо тянутся, но уже достигли своего максимального размера. Также позволяет в некотором роде управлять выравниванием элементов при выходе за границы строки.
justify-content: flex-start | flex-end | center | space-between | space-around
flex-start
(по умолчанию): элементы сдвигаются к началу строки;flex-end
: элементы сдвигаются к концу строки;center
: элементы выравниваются по центру строки;space-between
: элементы распределяются равномерно (первый элемент в начале строки, последний — в конце);space-around
: элементы распределяются равномерно с равным расстоянием между собой и границами строки.
align-items
Применяется к: родительскому элементу flex-контейнера.
Определяет поведение по умолчанию для того, как flex-элементы располагаются относительно поперечной оси на текущей строке. Считайте это версией justify-content
для поперечной оси (перпендикулярной к основной).
align-items: flex-start | flex-end | center | baseline | stretch
flex-start
: границаcross-start
для элементов располагается на позицииcross-start
;flex-end
: границаcross-end
для элементов располагается на позицииcross-end
;center
: элементы выравниваются по центру поперечной оси;baseline
: элементы выравниваются по своей базовой линии;stretch
(по умолчанию): элементы растягиваются, заполняя контейнер (с учётомmin-width
/max-width
).
align-content
Применяется к: родительскому элементу flex-контейнера.
Выравнивает строки flex-контейнера при наличии свободного места на поперечной оси аналогично тому, как это делает justify-content
на главной оси.
Замечание: это свойство не работает с однострочным flexbox.
align-content: flex-start | flex-end | center | space-between | space-around | stretch
flex-start
: строки выравниваются относительно начала контейнера;flex-end
: строки выравниваются относительно конца контейнера;center
: строки выравниваются по центру контейнера;space-between
: строки распределяются равномерно (первая строка в начале строки, последняя — в конце);space-around
: строки распределяются равномерно с равным расстоянием между собой;stretch
(по умолчанию): строки растягиваются, заполняя свободное пространство.
order
Применяется к: дочернему элементу / flex-элементу.
По умолчанию flex-элементы располагаются в исходном порядке. Тем не менее, свойство order
может управлять порядком их расположения в контейнере.
order: <integer>
flex-grow
Применяется к: дочернему элементу / flex-элементу.
Определяет для flex-элемента возможность «вырастать» при необходимости. Принимает безразмерное значение, служащее в качестве пропорции. Оно определяет, какую долю свободного места внутри контейнера элемент может занять.
Если у всех элементов свойство flex-grow
задано как 1
, то каждый потомок получит внутри контейнера одинаковый размер. Если вы задали одному из потомков значение 2
, то он заберёт в два раза больше места, чем другие.
flex-grow: <number> (по умолчанию 0)
Отрицательные числа не принимаются.
flex-shrink
Применяется к: дочернему элементу / flex-элементу.
Определяет для flex-элемента возможность сжиматься при необходимости.
flex-shrink: <number> (<b>default</b> 1)
Отрицательные числа не принимаются.
flex-basis
Применяется к: дочернему элементу / flex-элементу.
Определяет размер по умолчанию для элемента перед распределением пространства в контейнере.
flex-basis: <length> | auto (default auto)
flex
Применяется к: дочернему элементу / flex-элементу.
Это сокращение для flex-grow
, flex-shrink
и flex-basis
. Второй и третий параметры (flex-shrink
, flex-basis
) необязательны. Значение по умолчанию — 0 1 auto
.
flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
align-self
Применяется к: дочернему элементу / flex-элементу.
Позволяет переопределить выравнивание, заданное по умолчанию или в align-items
, для отдельных flex-элементов.
Обратитесь к описанию свойства align-items
для лучшего понимания доступных значений.
align-self: auto | flex-start | flex-end | center | baseline | stretch
Примеры
Начнём с очень-очень простого примера, встречающегося практически каждый день: выравнивание точно по центру. Нет ничего проще, если использовать flexbox.
.parent {
display: flex;
height: 300px; /* Або що завгодно */
}
.child {
width: 100px; /* Або що завгодно */
height: 100px; /* Або що завгодно */
margin: auto; /* Магія! */
}
Этот пример основывается на том, что margin
во flex-контейнере, заданный как auto
, поглощает лишнее пространство, поэтому задание отступа таким образом выровняет элемент ровно по центру по обеим осям.
Теперь давайте используем какие-нибудь свойства. Представьте набор из 6 элементов фиксированного размера (для красоты), но с возможностью изменения размера контейнера. Мы хотим равномерно распределить их по горизонтали, чтобы при изменении размера окна браузера всё выглядело хорошо (без @media
-запросов!).
.flex-container {
/* Спочатку створимо flex-контекст */
display: flex;
/* Тепер визначимо напрямок потоку і чи хочемо ми, щоб елементи
переносилися на новий рядок
* Пам'ятайте, що це так само, як і:
* flex-direction: row;
* flex-wrap: wrap;
*/
flex-flow: row wrap;
/* Тепер визначимо, як розподілятиметься простір */
justify-content: space-around;
}
Готово. Всё остальное — уже дело оформления.
Теперь представьте, что нам нужна выровненная по правому краю навигация в самом верху нашего сайта, но мы хотим, чтобы она выравнивалась по центру для экранов среднего размера и превращалась в один столбец на маленьких. Всё достаточно просто.
/* Великі екрани */
.navigation {
display: flex;
flex-flow: row wrap;
/* Зсуває елементи до кінця рядка по головній осі */
justify-content: flex-end;
}
/* Экрани середнього розміру */
@media all and (max-width: 800px) {
.navigation {
/* Для екранів середнього розміру ми вирівнюємо навігацію центром,
рівномірно розподіляючи вільне місце між елементами */
justify-content: space-around;
}
}
/* Маленькі екрани */
@media all and (max-width: 500px) {
.navigation {
/* На маленьких екранах замість рядка ми маємо елементи в стовпці */
flex-direction: column;
}
}
Давайте попробуем кое-что получше и поиграем с гибкостью flex-элементов! Как насчёт ориентированного на мобильные устройства трёхколоночного макета с полноширинной шапкой и подвалом? И другим порядком расположения.
.wrapper {
display: flex;
flex-flow: row wrap;
}
/* Задаємо всім елементам ширину 100% */
.header, .main, .nav, .aside, .footer {
flex: 1 100%;
}
/* У цьому випадку ми покладаємось на вихідний порядок для орієнтації на
* мобільні пристрої:
* 1. header
* 2. nav
* 3. main
* 4. aside
* 5. footer
*/
/* Екрани середнього розміру */
@media all and (min-width: 600px) {
/* Обидва сайдбари розташовуються в одному рядку */
.aside { flex: 1 auto; }
}
/* Великі екрани */
@media all and (min-width: 800px) {
/* Ми міняємо місцями елементи .aside-1 та .main, а також повідомляємо
* елементу .main забирати вдвічі більше місця, ніж сайдбари.
*/
.main { flex: 2 0px; }
.aside-1 { order: 1; }
.main { order: 2; }
.aside-2 { order: 3; }
.footer { order: 4; }
}
Поддержка браузерами
(modern)
означает поддержку нового синтаксиса из спецификации (display: flex;
)(hybrid)
означает поддержку старого неофициального синтаксиса из 2011 (display: flexbox;
)(old)
означает поддержку старого синтаксиса из 2009 (display: box;
)
|
Браузер Blackberry версии 10+ поддерживает новый синтаксис.
Для более подробной информации о том, как и когда использовать различные синтаксисы для обеспечения лучшей поддержки браузерами, обратитесь к этой статье (CSS-Tricks) или этой статье (DevOpera).
SASS-@mixin
для облегчения боли:
@mixin flexbox() {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
}
@mixin flex($values) {
-webkit-box-flex: $values;
-moz-box-flex: $values;
-webkit-flex: $values;
-ms-flex: $values;
flex: $values;
}
@mixin order($val) {
-webkit-box-ordinal-group: $val;
-moz-box-ordinal-group: $val;
-ms-flex-order: $val;
-webkit-order: $val;
order: $val;
}
.wrapper {
@include flexbox();
}
.item {
@include flex(1 200px);
@include order(2);
}