Окно браузера, мобильный телефон, умные часы и зеркальце из сказки про Белоснежку. На всех открыт один и тот же сайт.
Иллюстрация: Кира Кустова

Гайд по flexbox

Всё, что нужно знать про флексбоксы: основные термины, свойства флекс-контейнера и флекс-элементов, полезные ссылки по теме.

Время чтения: 13 мин

Что это?

Секция статьи "Что это?"

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

Идея флексбоксов появилась ещё в 2009 году, и этот стандарт до сих пор развивается и прорабатывается. Основная идея флексов — гибкое распределение места между элементами, гибкая расстановка, выравнивание, гибкое управление. Ключевое слово — гибкое, что и отражено в названии (flex — англ. гибко).

Основные термины

Секция статьи "Основные термины"
  • Флекс-контейнер: элемент, к которому применяется свойство display: flex. Вложенные в него элементы подчиняются правилам раскладки флексов.
  • Флекс-элемент: элемент, вложенный во флекс-контейнер.
Пример флекс-контейнера и вложенных в него флекс-элементов
  • Основная ось: основная направляющая флекс-контейнера, вдоль которой располагаются флекс-элементы.
  • Поперечная (побочная, перпендикулярная) ось: ось, идущая перпендикулярно основной. Позже вы поймёте, для чего она нужна.
Наглядный вид основной оси и поперечной оси
  • Начало / конец основной оси: точки в начале и в конце основной оси соответственно. Это пригодится нам для выравнивания флекс-элементов.
  • Начало / конец поперечной оси: точки в начале и в конце поперечной оси соответственно.
Наглядный вид начала/конца основной оси и начала/конца поперечной оси
  • Размер по основной оси (основной размер): размер флекс-элемента вдоль основной оси. Это может быть ширина или высота в зависимости от направления основной оси.
  • Размер по поперечной оси (поперечный размер): размер флекс-элемента вдоль поперечной оси. Это может быть ширина или высота в зависимости от направления поперечной оси. Этот размер всегда перпендикулярен основному размеру. Если основной размер — это ширина, то поперечный размер — это высота, и наоборот.
Наглядный вид размера по основной оси и по поперечной оси

Свойства флекс-контейнера

Секция статьи "Свойства флекс-контейнера"

display

Секция статьи "display"
        
          
          .container {  display: flex;}
          .container {
  display: flex;
}

        
        
          
        
      

Когда мы задаём какому-то элементу значение flex для свойства display, мы превращаем этот элемент в флекс-контейнер. Внутри него начинает действовать флекс-контекст, его дочерние элементы начинают подчиняться свойствам флексбокса.

Снаружи флекс-контейнер выглядит как блочный элемент — занимает всю ширину родителя, следующие за ним элементы в разметке переносятся на новую строку.

        
          
          .container {  display: inline-flex;}
          .container {
  display: inline-flex;
}

        
        
          
        
      

Если контейнеру задано значение inline-flex, то снаружи он начинает вести себя как строчный (инлайн) элемент — размеры зависят только от внутреннего контента, встаёт в строку с другими элементами. Внутри это ровно такой же флекс-контейнер, как и при предыдущем значении.

flex-direction

Секция статьи "flex-direction"

Свойство управления направлением основной и поперечной осей.

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

        
        
          
        
      

Возможные значения:

  • row (значение по умолчанию) — основная ось идёт горизонтально слева направо, поперечная ось идёт вертикально сверху вниз.
  • row-reverse — основная ось идёт горизонтально справа налево, поперечная ось идёт вертикально сверху вниз.
  • column — основная ось идёт вертикально сверху вниз, поперечная ось идёт горизонтально слева направо.
  • column-reverse — основная ось идёт вертикально снизу вверх, поперечная ось идёт горизонтально слева направо.
Пример свойства flex-direction

Важный момент: на сайтах с направлением текста справа налево, например, на сайте на арабском языке, для значений row и row-reverse основная ось будет идти в обратном направлении. Для значений column и column-reverse своё направление поменяет поперечная ось.

flex-wrap

Секция статьи "flex-wrap"
        
          
          .container {  display: flex;  flex-wrap: nowrap;}
          .container {
  display: flex;
  flex-wrap: nowrap;
}

        
        
          
        
      

По умолчанию значение у свойства flex-wrapnowrap. При этом флекс-элементы помещаются (или пытаются уместиться) в один ряд и не переносятся в новый ряд, даже если не влезают в размеры родителя.

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

Ещё одно возможное значение — wrap-reverse. В этом случае элементы будут располагаться снизу вверх, заполнив собой сперва нижний ряд, а те, что не влезли, перепрыгнут в ряд выше.

Пример свойства flex-wrap

flex-flow

Секция статьи "flex-flow"

Это свойство-шорткат для одновременного определения значений свойств flex-direction и flex-wrap.

        
          
          .container {  display: flex;  flex-flow: column wrap;}
          .container {
  display: flex;
  flex-flow: column wrap;
}

        
        
          
        
      

Или:

        
          
          .container {  display: flex;  flex-flow: row nowrap;}
          .container {
  display: flex;
  flex-flow: row nowrap;
}

        
        
          
        
      

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

justify-content

Секция статьи "justify-content"
        
          
          .container {  display: flex;  justify-content: space-between;}
          .container {
  display: flex;
  justify-content: space-between;
}

        
        
          
        
      

Свойство позволяет выравнивать флекс-элементы внутри флекс-контейнера по основной оси.

Возможные значения:

  • flex-start (значение по умолчанию) — элементы прижимаются к краю, от которого начинается основная ось.
  • flex-end — элементы прижимаются к краю, у которого основная ось заканчивается.
  • start — элементы прижимаются к тому краю, откуда начинается чтение на том языке, на котором отображается сайт. Например, для русского языка элементы прижмутся к левому краю при горизонтальной основной оси, а для арабского языка — к правому краю.
  • end — элементы прижимаются к краю, противоположному началу направления чтения на том языке, на котором отображается сайт. Например, при горизонтальной основной оси на русском языке элементы прижмутся к правому краю.
  • left — элементы прижмутся к левому краю родителя. В случае, если указано свойство flex-direction: column, значение срабатывает как start.
  • right — элементы прижмутся к правому краю. В случае, если указано свойство flex-direction: column, значение срабатывает как end.
  • center — элементы выстраиваются по центру родителя.
  • space-between — крайние элементы прижимаются к краям родителя, оставшиеся выстраиваются внутри контейнера равномерно, так, чтобы между ними были одинаковые отступы.
  • space-around — свободное пространство делится поровну между элементами и по половине от этой доли размещается по бокам от каждого элемента. Таким образом, между соседними элементами будет равное расстояние, а снаружи крайних элементов — по половине этого расстояния.
  • space-evenly — свободное место будет распределено так, чтобы расстояние между любыми двумя элементами было одинаковым и расстояние от крайних элементов до края было таким же.

Хотя большинство значений поддерживаются основными браузерами, с некоторыми из них могут быть трудности. Поэтому лучше на всякий случай проверяйте поддержку на Can I use.

align-items

Секция статьи "align-items"
        
          
          .container {  display: flex;  align-items: center;}
          .container {
  display: flex;
  align-items: center;
}

        
        
          
        
      

Свойство выравнивания элементов внутри контейнера по поперечной оси.

Возможные значения:

  • stretch (значение по умолчанию) — элементы растягиваются вдоль поперечной оси так, чтобы заполнить всего родителя. Это очень удобно, если вы делаете двухколоночный макет. Раньше приходилось при помощи разных костылей добиваться одинаковой высоты, а теперь достаточно сделать контейнер флексом, и колонки по умолчанию будут одной высоты.
  • flex-start или start — элементы выстраиваются у начала поперечной оси. Разница между ними лишь в том, что второе значение «уважает» направление чтения выбранного языка.
  • flex-end или end — элементы выстраиваются у конца поперечной оси. Разница между первым и вторым значениями аналогична предыдущему пункту.
  • center — элементы выстраиваются по центру поперечной оси.
  • baseline — элементы выравниваются по базовой линии текста. «Базовая линия» — baseline — воображаемая линия, проходящая по нижнему краю знаков шрифта (без учёта выносных элементов).

Это может быть сложно понять сразу, поэтому мы сделали демку. Обратите внимание, что вне зависимости от размера шрифта все блоки выравниваются по базовой линии первой строки.

Открыть демо в новой вкладке

align-content

Секция статьи "align-content"
        
          
          .container {  display: flex;  align-content: center;}
          .container {
  display: flex;
  align-content: center;
}

        
        
          
        
      

Свойство распределяет свободное пространство по поперечной оси между рядами флекс-элементов. Предположим, у вас 11 элементов в 3 рядах. Если размер родителя по поперечной оси позволяет, то при помощи align-content можно распределять строчки элементов: по верхнему краю, по нижнему, по центру или равномерно.

Не имеет видимого значения, если элементы располагаются в один ряд.

Возможные значения:

  • stretch (значение по умолчанию) — ряды растягиваются одинаково, так, чтобы занять всё доступное пространство родителя.
  • flex-start / start — все ряды располагаются у начала поперечной оси. Первое значение не зависит от направления чтения текущего языка, в отличие от второго.
  • flex-end / end — все ряды располагаются у конца поперечной оси. end «уважает» направление чтения текущего языка.
  • center — ряды выравниваются по центру родителя.
  • space-between — первый ряд прижимается к началу поперечной оси, последний — к концу поперечной оси, а остальные располагаются так, чтобы свободное пространство было поделено на отступы между ними равномерно.
  • space-around — отступы у каждого ряда равнозначны отступам у любого другого ряда.
  • space-evenly — отступы между рядами и от краёв родителя одинаковые.

gap

Секция статьи "gap"

С помощью этого свойства можно с лёгкостью задавать отступы между строками и столбцами.

Является краткой записью свойств row-gap и column-gap.

Может иметь одно или два значения. Если указано только одно, то column-gap автоматически равен row-gap. Если указаны два значения, то первое будет задавать отступы между рядами (row-gap), а второе — между колонками (column-gap).

Значения можно указывать в любых доступных единицах измерения, включая проценты.
Допускается использование функции calc().

        
          
          .container {  display: flex;  gap: 30px calc(10rem - 10px);}
          .container {
  display: flex;
  gap: 30px calc(10rem - 10px);
}

        
        
          
        
      

Свойства флекс-элемента

Секция статьи "Свойства флекс-элемента"

order

Секция статьи "order"
        
          
          .container {  display: flex;}.item {  order: 3;}
          .container {
  display: flex;
}

.item {
  order: 3;
}

        
        
          
        
      

При помощи свойства order можно менять порядок отображения флекс-элементов внутри флекс-контейнера.

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

Значение задаётся в виде целого отрицательного или положительного числа. Элементы встают по возрастающей.

Пример свойства флекс-элементов order

flex-grow

Секция статьи "flex-grow"
        
          
          .container {  display: flex;}.item {  flex-grow: 1;}
          .container {
  display: flex;
}

.item {
  flex-grow: 1;
}

        
        
          
        
      

Это свойство указывает, может ли вырастать флекс-элемент при наличии свободного места, и насколько. По умолчанию значение равно 0. Значением может быть любое положительное целое число (включая 0).

Если у всех флекс-элементов будет прописано flex-grow: 1, то свободное пространство в контейнере будет равномерно распределено между всеми.

Если при этом одному из элементов мы зададим flex-grow: 2, то он постарается занять в два раза больше свободного места, чем его соседи.

flex-shrink

Секция статьи "flex-shrink"
        
          
          .container {  display: flex;}.item {  flex-shrink: 3;}
          .container {
  display: flex;
}

.item {
  flex-shrink: 3;
}

        
        
          
        
      

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

Чем больше значение у этого свойства, тем быстрее элемент будет сжиматься по сравнению с соседями, имеющими меньшее значение.

Значение по умолчанию — 1. Значением может быть любое целое положительное число (включая 0).

Два предыдущих свойства работают с пропорциональным разделением пространства, не с конкретными размерами. Они довольно непростые, даже опытный разработчик не всегда знает, как они в точности работают. Загляните в конец статьи, если хотите подробнее почитать о каждом из них.

flex-basis

Секция статьи "flex-basis"
        
          
          .container {  display: flex;}.item {  flex-basis: 250px;}
          .container {
  display: flex;
}

.item {
  flex-basis: 250px;
}

        
        
          
        
      

Свойство flex-basis указывает на размер элемента до того, как свободное место будет распределено (см. flex-grow).

Значением может быть размер в любых относительных или абсолютных единицах: 20rem, 5vw, 250px. А также можно использовать ключевое слово auto (значение по умолчанию). В этом случае при расчёте размера элемента будут приниматься во внимание значения свойств width, max-width, min-width или аналогичные свойства высоты, в зависимости от того, в каком направлении идёт основная ось.

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

flex

Секция статьи "flex"
        
          
          .container {  display: flex;}.item {  flex: 1 1 auto;}
          .container {
  display: flex;
}

.item {
  flex: 1 1 auto;
}

        
        
          
        
      

Свойство-шорткат, с помощью которого можно указать значение трёх свойств одновременно: flex-grow, flex-shrink и flex-basis. Первое значение является обязательным, остальные опциональны.

Значение по умолчанию: 0 1 auto, что расшифровывается как flex-grow: 0, flex-shrink: 1, flex-basis: auto.

Возможные значения:

        
          
          /* 0 0 auto */flex: none;/* Одно значение, число без единиц: flex-grow */flex: 2;/* Одно значение, ширина/высота: flex-basis */flex: 10em;flex: 30px;flex: auto;flex: content;/* Два значения: flex-grow | flex-basis */flex: 1 30px;/* Два значения: flex-grow | flex-shrink */flex: 2 2;/* Три значения: flex-grow | flex-shrink | flex-basis */flex: 2 2 10%;/* Глобальные значения */flex: inherit;flex: initial;flex: unset;
          /* 0 0 auto */
flex: none;

/* Одно значение, число без единиц: flex-grow */
flex: 2;

/* Одно значение, ширина/высота: flex-basis */
flex: 10em;
flex: 30px;
flex: auto;
flex: content;

/* Два значения: flex-grow | flex-basis */
flex: 1 30px;

/* Два значения: flex-grow | flex-shrink */
flex: 2 2;

/* Три значения: flex-grow | flex-shrink | flex-basis */
flex: 2 2 10%;

/* Глобальные значения */
flex: inherit;
flex: initial;
flex: unset;

        
        
          
        
      

align-self

Секция статьи "align-self"
        
          
          .container {  display: flex;  align-items: flex-start;}.item {  align-self: flex-end;}
          .container {
  display: flex;
  align-items: flex-start;
}

.item {
  align-self: flex-end;
}

        
        
          
        
      

При помощи этого свойства можно выровнять один или несколько элементов иначе, чем задано у родительского элемента. Например, в коде выше у родителя задано выравнивание вложенных элементов по верхнему краю родителя. А для элемента с классом .item мы задаём выравнивание по нижнему краю.

Ссылки

Секция статьи "Ссылки"
  1. Как реально работает flex-grow
  2. Как реально работает flex-shrink
  3. Песочница Флексбоксов
  4. Game: Flexbox Froggy
  5. Game: Flexbox Defense
  6. Game: Flexbox Ducky
  7. Курс по Флексбоксам от Wes Bos

На практике

Секция статьи "На практике"

Андрей Захаров советует

Секция статьи "Андрей Захаров советует"

Свойство margin со значением auto позволяет очень гибко управлять выравниванием флекс-элементов. Например если необходимо, чтобы логотип и заголовок были в левой части контейнера, а например кнопка меню прижата к правой части, то достаточно задать кнопке меню значение margin-left: auto, в этом случае отступ займёт всё свободное пространство flex контейнера и элемент с кнопкой меню окажется прижат к правой части. Отличие от justify-content: space-between здесь в том, что нет необходимости в дополнительной обёртке для логотипа и заголовка. Так же можно задать нескольким элементам свойство margin-*: auto, в этом случае всё свободное пространство контейнера разделится в равных частях между отступами элементов, у которых задано это свойство. Данный приём расширяет ту функциональность, которую нам даёт свойство justify-content, мы можем задавать отступы только между необходимыми элементами, а не всеми сразу.

Егор Левченко советует

Секция статьи "Егор Левченко советует"

Во время работы стоит быть особенно внимательным со свойствами, которые меняют внешнее расположение элементов внутри flex-контейнера: например flex-direction: row-reverse или column-reverse, а также со свойством order.

Дело в том, что контент меняет своё расположение только визуально, CSS-свойствами, а значит, в теле сайта элементы окажутся в том порядке, в котором вы их расположили в HTML-файле. Позаботьтесь о людях, которые пользуются скринридерами, и не меняйте положение элементов на странице CSS-свойствами без крайней необходимости.


Цель крутого фронтендера — решать задачи бизнеса, а не писать много кода. Центрирование блока внутри родителя можно сократить до двух строк:

  1. Родителя сделать флекс-контейнером.
  2. Дочернему элементу задать margin: auto.

Ждём сокращения кода до одной строки =)

Алёна Батицкая советует

Секция статьи "Алёна Батицкая советует"

🛠 Раньше было затруднительно прижать футер к нижнему краю экрана вне зависимости от количества контента на странице. Приходилось идти на всякие ухищрения и городить костыли. Теперь с появлением флексов всё стало просто.

Оборачиваем всю страницу в блок, делаем его флекс-контейнером, внутрь вкладываем хэдер, мейн и футер. Родителю задаём flex-direction: column чтобы блоки встали друг под другом, а не в ряд, и min-height: 100vh, чтобы он занимал как минимум всю высоту экрана. Мейну задаём flex: 1, и вуаля! Центральный блок страницы будет всегда растягиваться на всё доступное свободное пространство. Из-за этого футер всегда будет прижиматься к нижнему краю страницы. При этом, если контента в мейне будет больше чем на один экран, то он растянется и подстроится, ничего не сломается.

🛠 Частой проблемой в вёрстке до появления флексбоксов было вертикальное выравнивание блока внутри родителя. Использовались хаки с трансформом, отступами, высотой строки и прочие костыли.

Теперь же всё делается в три строки:

  1. Родителя делаем флекс-контейнером.
  2. Задаём ему выравнивание по основной оси по центру justify-content: center.
  3. Задаём ему выравнивание по поперечной оси по центру align-items: center.

Получаем выровненный по центру вложенный блок.

На собеседовании

Секция статьи "На собеседовании"

Это партнёрская рубрика, мы выпускаем её совместно с сервисом онлайн-образования Яндекс Практикум. Приносите вопрос, на который не знаете ответа, в задачи, мы разложим всё по полочкам и опубликуем. Если знаете ответ, присылайте пулреквест на GitHub.

Это вопрос без ответа. Вы можете помочь! Почитайте о том, как контрибьютить в Доку.