Введение
Наше полное руководство по Flexbox-макетам CSS. В этом руководстве подробно объясняется всё о Flexbox, с упором на все возможные атрибуты родительского элемента (flex-контейнера) и дочерних элементов (flex-элементов). Оно также включает историю, примеры, шаблоны и таблицу поддержки браузерами.
Контекст
Модуль макета Flexbox (рекомендация W3C от октября 2017 г.) призван обеспечить более эффективный способ организации, выравнивания и распределения пространства между элементами внутри контейнера, даже если их размер неизвестен и/или является динамическим (отсюда и слово “flex”).
Основная идея гибкой компоновки заключается в том, чтобы контейнер мог изменять ширину/высоту (и порядок) своих элементов для оптимального заполнения доступного пространства (в основном для поддержки различных устройств отображения и размеров экранов). Гибкий контейнер расширяет элементы, заполняя доступное свободное пространство, или сжимает их, предотвращая переполнение.
Самое главное, что flexbox-макет ориентирован, в отличие от обычных макетов (блок, выровненный по вертикали и встроенный в горизонтальную разметку). Хотя они хорошо подходят для страниц, им не хватает гибкости (без шуток) для поддержки больших или сложных приложений (особенно когда речь идёт об изменении ориентации, размера, растяжении, сжатии и т. д.).
Примечание: макет Flexbox больше подходит для компонентов приложений и макетов небольшого масштаба, тогда как макет Grid предназначен для макетов большего масштаба.
Основы и терминология
Поскольку Flexbox — это полноценный модуль, а не отдельная функция, он включает в себя множество функций, включая полный набор свойств. Некоторые из них предназначены для установки в контейнере (родительском элементе, называемом “flex-контейнером”), а другие — для установки в дочерних элементах (так называемых “flex-элементах”).
Если “обычная” компоновка основана как на блочном, так и на линейном направлениях потока, то гибкая компоновка основана на “гибких направлениях потока”. Ознакомьтесь с этой формой спецификации, и она объясняет основную идею гибкой компоновки.
Элементы размещаются вдоль главной оси (от главного начала до главного конца) или поперечной оси (от поперечного начала до поперечного конца).
- Главная ось – главная ось flex-контейнера – это основная ось, вдоль которой размещаются flex-элементы. Обратите внимание: она не обязательно горизонтальна. Это зависит от свойства flex-direction (см. ниже).
- Главное начало | Главное конец – Гибкие предметы размещаются внутри контейнера, начиная с главного начала и до главного конца.
- Исходный размер – ширина или высота Flex-элемента, в зависимости от того, какое из них находится в исходном измерении, является исходным размером элемента. Свойство исходного размера Flex-элемента – это свойство “width” (ширина) или “height” (высота), в зависимости от того, какое из них находится в исходном измерении.
- Поперечная ось – ось, перпендикулярная главной оси, называется поперечной осью. Её направление зависит от направления главной оси.
- Поперечный старт | поперечный конец – гибкие линии заполняются предметами и размещаются в контейнере, начиная со стороны поперечного старта гибкого контейнера и двигаясь к поперечному концу.
- Размер по ширине – ширина или высота Flex-элемента, в зависимости от того, что находится в измерении по ширине, является размером по ширине элемента. Свойство размера по ширине – это значение по ширине или высоте, в зависимости от того, что находится в измерении по ширине.
Возможности Flexbox
Недвижимость для родителей
(контейнер)
Отображать
Это определяет гибкий контейнер. В зависимости от заданного значения, он может быть встроенным или блочным. Он предоставляет гибкий контекст для всех своих прямых дочерних элементов.
.container {
display: flex; /* or inline-flex */
}направление изгиба
Это создаёт основную ось, определяющую направление размещения flex-элементов внутри flex-контейнера. Flexbox (за исключением опционального обёртывания) — это концепция однонаправленной компоновки. Flex-элементы можно представить себе как расположенные преимущественно в горизонтальных рядах или вертикальных столбцах.
.container {
flex-direction: row | row-reverse | column | column-reverse;
}- ROW (по умолчанию): слева направо в формате LTR. Справа налево в формате RTL.
- обратная строка: справа налево в ltr. слева направо в rtl
- КОЛОНКА: Как строка, но сверху вниз
- Колонка-обратная: как обратная строка, но снизу вверх
Flex Wrap
По умолчанию все гибкие элементы стремятся уместиться на одной линии. Вы можете изменить это и при необходимости разрешить закрытие элементов с помощью этого свойства.
.container {
flex-wrap: nowrap | wrap | wrap-reverse;
}- nowrap (по умолчанию): все flex-элементы будут перенесены на одну строку
- обертывание: гибкие элементы обертываются на нескольких линиях сверху вниз.
- wrap-reverse: Гибкие элементы размещаются на нескольких строках снизу вверх.
FLEX-Flow
Это сокращённое обозначение свойств flex-direction и flex-width, которые вместе определяют главную и поперечную оси flex-контейнера. Значение по умолчанию — row nowrap.
.container {
flex-flow: column wrap;
}Justify-Content
Это задаёт выравнивание по главной оси. Это помогает распределить избыточное пустое пространство, когда все гибкие элементы в строке являются негибкими или гибкими, но достигли максимального размера. Это также позволяет контролировать выравнивание элементов, когда они выходят за пределы строки.
.container {
justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly | start | end | left | right ... + safe | unsafe;
}- flex-start (по умолчанию): элементы упаковываются в направлении начала направления гибкости.
- гибкий конец: предметы упаковываются в направлении конца гибкого направления.
- СТАРТ: Элементы упаковываются в направлении начала направления режима письма.
- КОНЕЦ: Элементы упаковываются в конце направления режима записи.
- СЛЕВА: Элементы упаковываются по направлению к левому краю контейнера, если это не противоречит направлению изгиба, в таком случае это действует как начало.
- ПРАВИЛЬНО: Предметы упаковываются по направлению к правому краю контейнера, если нет смысла делать это в этом направлении, тогда он действует как конец.
- ЦЕНТР: Элементы выравниваются по центру линии.
- Пространство между ними: предметы равномерно распределены в ряду. Первый предмет находится на линии старта, последний — на линии финиша.
- Space-Around: Элементы равномерно распределены в ряд с равным пространством вокруг них. Обратите внимание, что визуально пространство не одинаковое, поскольку все элементы имеют одинаковое пространство с обеих сторон. Первый элемент будет иметь одну единицу пространства у края контейнера, но между следующим элементом будет две единицы пространства, поскольку для следующего элемента применяется свой собственный интервал.
- Равномерно распределено: элементы распределяются таким образом, чтобы расстояние между любыми двумя элементами (и расстояние до краев) было одинаковым.
Есть также два дополнительных ключевых слова, которые можно сочетать с этими значениями: safe и insecure. Использование safe гарантирует, что независимо от способа позиционирования вы не сможете вывести элемент за пределы страницы (например, за её верхнюю часть), что сделает невозможным прокрутку содержимого (это называется «потерей данных»).
Выравнивание элементов
Это определяет поведение по умолчанию для расположения гибких элементов вдоль поперечной оси в текущей строке. Это можно представить как вариант выравнивания содержимого по поперечной оси (перпендикулярной основной оси).
.container {
align-items: stretch | flex-start | flex-end | center | baseline | first baseline | last baseline | start | end | self-start | self-end + ... safe | unsafe;
}- STREtch (по умолчанию): растянуть для заполнения контейнера (при этом сохраняется минимальная и максимальная ширина)
- flex-start / start / self-start: элементы размещаются в начале поперечной оси. Разница между ними незначительна и заключается в соблюдении правил направления гибкости или правил режима письма.
- flex-end / end / self-end: элементы размещаются в конце поперечной оси. Разница, опять же, незначительна и заключается в соблюдении правил направления flex по сравнению с правилами режима письма.
- ЦЕНТР: Элементы расположены на поперечной оси
- BASEline: элементы выравниваются по своим базовым линиям
ALign-Content
Если на поперечной оси есть дополнительное пространство, он выравнивает линии гибкого контейнера внутри, аналогично тому, как justify-content выравнивает отдельные элементы на главной оси.
.container {
align-content: flex-start | flex-end | center | space-between | space-around | space-evenly | stretch | start | end | baseline | first baseline | last baseline + ... safe | unsafe;
}- Нормально (по умолчанию): элементы упаковываются в положение по умолчанию, как будто значение не задано.
- flex-start / start: Элементы переносятся в начало контейнера. flex-start (с большей поддержкой) указывает направление flex, тогда как start учитывает направление режима записи.
- flex-end / end: Элементы, которые переносятся в конец контейнера. (Дополнительная поддержка) flex-end указывает направление изгиба, тогда как end учитывает направление режима записи.
- ЦЕНТР: Предметы, находящиеся в центре контейнера.
- Пробел между элементами: элементы располагаются равномерно. Первая строка находится в начале контейнера, а последняя — в конце.
- Пространство вокруг: элементы равномерно распределены с одинаковым пространством вокруг каждой строки.
- Равномерное распределение: предметы распределены равномерно, вокруг них есть одинаковое пространство.
- растягивание: линии растягиваются, чтобы занять оставшееся пространство.
Пробел, Пробел между строками, Пробел между столбцами
Свойство gap явно задаёт расстояние между гибкими элементами. Это расстояние применяется только между элементами, а не к внешним краям.
.container {
display: flex;
...
gap: 10px;
gap: 10px 20px; /* row-gap column gap */
row-gap: 10px;
column-gap: 20px;
}Такое поведение можно рассматривать как минимальное отступание, то есть если отступ каким-то образом больше (например, из-за justify-content: spacing-between; ), то этот зазор будет иметь эффект только тогда, когда это пространство станет меньше.
Это касается не только Flexbox, пробелы также работают в сетках и многоколоночных макетах.
Префикс Flexbox
Flexbox требует определённых вендорных префиксов для поддержки максимально возможного количества браузеров. Это подразумевает не только добавление вендорного префикса к атрибутам, но и использование совершенно разных имён и значений свойств. Это связано с тем, что спецификация Flexbox со временем менялась, создавая «старые», «промежуточные» и «новые» версии.
Возможно, лучший способ справиться с этим — использовать новый (и окончательный) синтаксис и пропускать CSS через Autoprefixer, который эффективно использует пробелы.
В качестве альтернативы, вот 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);
}Примеры
Начнём с очень-очень простого примера, решающего практически повседневную задачу: идеальную фокусировку. С Flexbox всё проще некуда.
<ul class="navigation">
<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Products</a></li>
<li><a href="#">Contact</a></li>
</ul>.parent {
display: flex;
height: 300px; /* Or whatever */
}
.child {
width: 100px; /* Or whatever */
height: 100px; /* Or whatever */
margin: auto; /* Magic! */
}Это связано с тем, что автоматически устанавливаемые поля в гибком контейнере поглощают лишнее пространство. Таким образом, установка автоматически устанавливаемых полей позволит идеально центрировать элемент по обеим осям.
Теперь давайте используем ещё несколько свойств. Рассмотрим список из 6 элементов, каждый из которых имеет фиксированные размеры, но может масштабироваться автоматически. Мы хотим, чтобы они были равномерно распределены по горизонтальной оси, чтобы при изменении размера окна браузера всё корректно масштабировалось без каких-либо медиа-запросов.
.flex-container {
/* We first create a flex layout context */
display: flex;
/* Then we define the flow direction
and if we allow the items to wrap
* Remember this is the same as:
* flex-direction: row;
* flex-wrap: wrap;
*/
flex-flow: row wrap;
/* Then we define how is distributed the remaining space */
justify-content: space-around;
}Готово. Всё остальное — просто вопрос стиля. Ниже показано перо. Обязательно зайдите на CodePen и измените размер окон, чтобы увидеть результат.
Давайте попробуем что-нибудь другое. Представьте, что у нас есть элемент навигации, выровненный по правому краю в верхней части сайта, но мы хотим расположить его по центру на экранах среднего размера и сделать его одноколоночным на устройствах с небольшим экраном. Это достаточно просто.
/* Large */
.navigation {
display: flex;
flex-flow: row wrap;
/* This aligns items to the end line on main-axis */
justify-content: flex-end;
}
/* Medium screens */
@media all and (max-width: 800px) {
.navigation {
/* When on medium sized screens, we center it by evenly distributing empty space around items */
justify-content: space-around;
}
}
/* Small screens */
@media all and (max-width: 500px) {
.navigation {
/* On small screens, we are no longer using row direction but column */
flex-direction: column;
}
}Давайте попробуем что-нибудь получше, поэкспериментировав с гибкостью гибких элементов! Как насчёт трёхколоночного макета, ориентированного на мобильные устройства, с заголовком и подвалом на всю ширину страницы? И независимо от порядка исходного кода.
<div class="wrapper">
<header class="header">Header</header>
<article class="main">
<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>
</article>
<aside class="aside aside-1">Aside 1</aside>
<aside class="aside aside-2">Aside 2</aside>
<footer class="footer">Footer</footer>
</div>.wrapper {
display: flex;
flex-flow: row wrap;
}
/* We tell all items to be 100% width, via flex-basis */
.wrapper > * {
flex: 1 100%;
}
/* We rely on source order for mobile-first approach
* in this case:
* 1. header
* 2. article
* 3. aside 1
* 4. aside 2
* 5. footer
*/
/* Medium screens */
@media all and (min-width: 600px) {
/* We tell both sidebars to share a row */
.aside { flex: 1 auto; }
}
/* Large screens */
@media all and (min-width: 800px) {
/* We invert order of first sidebar and main
* And tell the main element to take twice as much width as the other two sidebars
*/
.main { flex: 3 0px; }
.aside-1 { order: 1; }
.main { order: 2; }
.aside-2 { order: 3; }
.footer { order: 4; }
}











