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

Гайд по flexbox

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

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

Что это?

Скопировано

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

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

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

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

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

Скопировано

display

Скопировано
        
          
          .container {  display: flex;}
          .container {
  display: flex;
}

        
        
          
        
      

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

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

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

        
        
          
        
      

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

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

Скопировано
        
          
          .container {  display: flex;  flex-wrap: nowrap;}
          .container {
  display: flex;
  flex-wrap: nowrap;
}

        
        
          
        
      

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

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

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

Пример свойства flex-wrap
Открыть демо в новой вкладке

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

Скопировано
        
          
          .container {  display: flex;  justify-content: space-between;}
          .container {
  display: flex;
  justify-content: space-between;
}

        
        
          
        
      

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

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

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

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

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

Скопировано
        
          
          .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

Скопировано

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

Является краткой записью свойств 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

Скопировано
        
          
          .container {  display: flex;}.item {  order: 3;}
          .container {
  display: flex;
}

.item {
  order: 3;
}

        
        
          
        
      

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

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

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

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

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

Скопировано
        
          
          .container {  display: flex;}.item {  flex-shrink: 3;}
          .container {
  display: flex;
}

.item {
  flex-shrink: 3;
}

        
        
          
        
      

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

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

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

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

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

Скопировано
        
          
          .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

Скопировано
        
          
          .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.

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

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

Скопировано
Задать вопрос в рубрику
🤚 Я знаю ответ

Матвей Романов  отвечает

Скопировано

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

Во всех остальных случаях можно смело использовать флексбоксы.