Что такое Flexbox

Flexbox — это модель раскладки CSS, которая позволяет управлять расположением элементов внутри контейнера.

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

Flexbox особенно хорошо подходит для небольших и средних компонентов интерфейса:

  • карточек;
  • кнопок и групп кнопок;
  • панелей;
  • меню;
  • шапок;
  • элементов списков;
  • блоков с иконкой и текстом.

Начнем с самой основы: что происходит с элементами после того, как контейнер становится flex-контейнером.

Как элементы располагаются без Flexbox

Представим простой контейнер с тремя элементами:

<div class="container">
  <div class="item">Первый</div>
  <div class="item">Второй</div>
  <div class="item">Третий</div>
</div>

Если не задавать контейнеру никаких специальных свойств, блочные элементы располагаются друг под другом:

.container {
  /* ничего особенного */
}

Получится примерно так:

Это обычное поведение блочных элементов.

Display: flex

Чтобы контейнер стал flex-контейнером, ему нужно задать:

.container {
  display: flex;
}

После этого непосредственные дочерние элементы контейнера становятся flex-элементами.

Никаких дополнительных свойств для этого не потребовалось.

И это главная идея, которую важно запомнить:

display: flex задается родителю, а не элементам, которые мы хотим расположить.

Если у нас есть:

<div class="container">
  <div>Первый</div>
  <div>Второй</div>
  <div>Третий</div>
</div>

то Flexbox включается так:

.container {
  display: flex;
}

Flex-контейнер и flex-элементы

После применения display: flex у нас появляются два важных понятия.

Flex-контейнер — элемент, которому задано display: flex.

Flex-элементы — его непосредственные дочерние элементы.

Например:

<div class="container">
  <div class="item">Первый</div>
  <div class="item">Второй</div>
  <div class="item">Третий</div>
</div>
.container {
  display: flex;
}

Здесь:

  • .container — flex-контейнер;
  • три .item — flex-элементы.

Важно именно слово «непосредственные».

Рассмотрим другой пример:

<div class="container">
  <div class="item">
    <span>Первый</span>
  </div>

  <div class="item">
    <span>Второй</span>
  </div>
</div>

Flex-элементами здесь являются .item, потому что именно они находятся непосредственно внутри .container.

А span не становится flex-элементом .container.

При этом ничто не мешает самому .item тоже стать flex-контейнером:

.container {
  display: flex;
}

.item {
  display: flex;
}

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

Главная и поперечная оси

У flex-контейнера есть две оси:

  • главная ось (main axis);
  • поперечная ось (cross axis).

По умолчанию элементы располагаются вдоль главной оси слева направо. Поперечная ось в этом случае идет сверху вниз.

Позже мы научимся менять направление и увидим, что оси могут поменяться местами.

Расстояние между элементами — gap

Еще одна очень частая задача — задать одинаковое расстояние между flex-элементами.

Для этого используется gap.

Например:

.container {
  display: flex;
  gap: 16px;
}

Теперь между элементами будет расстояние 16 пикселей:

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

Раньше мы писали так:

.item {
  margin-right: 16px;
}

.item:last-child {
  margin-right: 0;
}

Теперь достаточно:

.container {
  display: flex;
  gap: 16px;
}

gap можно задавать не только одним значением.

Например:

.container {
  display: flex;
  gap: 12px 24px;
}

Здесь первое значение отвечает за расстояние между строками, а второе — между элементами в строке.

Однако пока мы не работаем с переносом элементов на несколько строк, поэтому подробно разбирать это поведение будем позже.

Flex и inline-flex

Кроме display: flex существует display: inline-flex. Оба значения создают flex-контейнер.

Разница заключается в поведении самого контейнера относительно окружающего содержимого.

display: flex

Flex-контейнер ведет себя как блочный элемент.

Например:

<div class="container">
  ...
</div>
.container {
  display: flex;
}

Такой контейнер обычно занимает доступную ширину строки.

display: inline-flex

inline-flex тоже создает flex-контейнер, но сам контейнер ведет себя подобно строчно-блочному элементу.

Он может занимать только необходимую ему ширину и находиться в одной строке с окружающим содержимым.

Например:

<p>
  Статус:
  <span class="badge">Онлайн</span>
</p>
.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

Это удобно для небольших элементов интерфейса:

  • бейджей;
  • кнопок;
  • тегов;
  • статусов;
  • небольших элементов с иконкой и текстом.

При этом внутри inline-flex всё работает как обычный Flexbox. Это означает одновременно две вещи:

  1. сам .badge ведет себя как строчно-блочный элемент;
  2. его внутренние элементы располагаются по правилам Flexbox.

Не стоит воспринимать inline-flex как «другой Flexbox». Это тот же Flexbox, только с другим поведением самого контейнера в потоке документа.

Что важно запомнить

На этом этапе вам достаточно уверенно понимать несколько вещей.

1. Flexbox включается у родителя

.container {
  display: flex;
}

После этого его непосредственные дочерние элементы становятся flex-элементами.

2. У Flexbox есть две оси

  • главная;
  • поперечная.

По умолчанию главная ось направлена слева направо, а поперечная — сверху вниз.

3. gap задает расстояние между элементами

.container {
  display: flex;
  gap: 16px;
}

4. flex и inline-flex — не одно и то же

Оба создают flex-контейнеры, но сам контейнер по-разному ведет себя в обычном потоке документа.

5. Flexbox можно использовать на разных уровнях

Один элемент может одновременно быть:

  • flex-элементом своего родителя;
  • flex-контейнером для собственных детей.

Это позволяет собирать сложные компоненты из небольших независимых блоков.

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

предыдущий пост следующий пост