← назад к разделу

Flexbox — рабочая раскладка современного веба: панели, меню, карточки, формы, «прижать кнопку вправо», «выровнять по центру» — всё это он. Модель одномерная: контейнер раскладывает детей вдоль одной оси и умеет гибко распределять между ними место. Ключ к пониманию — оси и три свойства гибкости.

Контейнер, оси и направление

display: flex на контейнере включает раскладку для его прямых детей:

.toolbar { display: flex; }

Дети встают в ряд вдоль главной оси (main axis); перпендикулярна ей поперечная (cross axis). Куда смотрит главная ось, задаёт flex-direction: row (умолчание, слева направо), column (сверху вниз), плюс реверсы. Все дальнейшие свойства привязаны к осям, а не к сторонам экрана — поменяли direction, и «горизонтальное» выравнивание стало вертикальным. Это не причуда, а сила: одна и та же логика раскладывает и строку тулбара, и колонку сайдбара.

По умолчанию дети не переносятся и могут ужиматься; flex-wrap: wrap разрешает перенос на новые линии — так строят «резиновые» галереи тегов и карточек.

Выравнивание: justify против align

Пара, которую путают всегда, различается осью:

  • justify-content — распределение вдоль главной оси: flex-start, center, flex-end, space-between (крайние к краям, остальное поровну между), space-around, space-evenly.
  • align-items — выравнивание по поперечной оси: stretch (умолчание — растянуть по высоте ряда), center, flex-start, flex-end, baseline (по базовой линии текста — для строк с разным размером шрифта).
.header {
  display: flex;
  justify-content: space-between; /* лого влево, меню вправо */
  align-items: center;            /* всё по вертикальному центру */
}

Идеальное центрирование, над которым веб бился десятилетие, — три строки: display: flex; justify-content: center; align-items: center.

Точечные инструменты: align-self переопределяет align-items для одного ребёнка; margin-left: auto у ребёнка съедает всё свободное место слева — идиома «прижать последний элемент к противоположному краю» без обёрток. order меняет визуальный порядок без правки разметки (осторожно: порядок таба и скринридера остаётся по DOM — расхождение бьёт по доступности).

Отступы между детьми — свойство gap: честные промежутки только между элементами, без margin-хаков и «съедания» крайних отступов. C flex-wrap задаёт и межстрочные интервалы.

Гибкость: grow, shrink, basis

Сердце flexbox — как дети делят место. У каждого ребёнка тройка свойств:

  • flex-basis — стартовый размер вдоль главной оси (до распределения); auto — от содержимого.
  • flex-grow — доля свободного места, которую ребёнок забирает (0 — не растёт).
  • flex-shrink — готовность ужиматься при нехватке места (1 по умолчанию — ужимаются все).

Пишут их шорткатом flex: grow shrink basis. Три пресета покрывают 95 % задач:

.item-a { flex: none; }    /* 0 0 auto — жёсткий: по контенту, не растёт, не жмётся */
.item-b { flex: auto; }    /* 1 1 auto — от контента, добор места пропорционально */
.item-c { flex: 1; }       /* 1 1 0   — РАВНЫЕ колонки: стартуем с нуля, делим всё */

Разница flex: auto и flex: 1 — в basis: auto делит только свободное место (кто был больше контентом, тот и останется больше), а flex: 1 обнуляет стартовые размеры и делит всё — колонки получаются строго равными. Классика — «инпут занимает всё, кнопка по размеру»:

.search { display: flex; gap: 8px; }
.search input { flex: 1; }
.search button { flex: none; }

Переполнение и min-width: 0

Самые известные flexbox-грабли. Внутри flex: 1-колонки лежит длинная строка без пробелов (URL, код) — и колонка отказывается ужиматься, ломая раскладку. Причина: у flex-детей min-width: auto — «не уже своего контента». Лечение — разрешить ужиматься:

.column { flex: 1; min-width: 0; }
.column .title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

Без min-width: 0 не работает и обрезание текста многоточием внутри flex-колонок — теперь вы знаете, почему.

Коротко

  • Flex — одномерная раскладка: главная ось (direction) и поперечная. Все свойства привязаны к осям, не к сторонам экрана.
  • justify-content — вдоль главной оси, align-items — поперёк. Центрирование чего угодно — три строки.
  • Тройка гибкости: basis (старт), grow (доля свободного), shrink (ужимаемость). flex: 1 — равные колонки, flex: none — жёсткий элемент, flex: auto — от контента с добором.
  • gap вместо margin-хаков; margin-left: auto — прижать элемент к краю; order меняет только визуальный порядок (доступность!).
  • Не ужимается / не работает ellipsis — ставьте min-width: 0 flex-ребёнку.

Что почитать дальше

  • Grid — двумерная раскладка: когда рядов и колонок много и они связаны.
  • Позиционирование — предыдущая тема цикла.
  • Блочная модель — почему во flex-контейнере не схлопываются margin.