Урок 08. Теория: оси, выравнивание, рост и сжатие

📁 Раздел: Раскладка ⏱️ Время изучения: ~50 мин 🎯 Сложность: Средняя

⚡ Кратко

Главная ось задаётся направлением: у flex она горизонтальная, у flex-col — вертикальная. justify-* распределяет по главной оси, items-* выравнивает по поперечной. Элементы по умолчанию сжимаются — поэтому иконкам нужен shrink-0, а текстовым блокам с обрезкой — min-w-0.

Две оси — единственное, что нужно понять

Flex-контейнер раскладывает детей вдоль главной оси и выравнивает поперёк неё. Всё остальное — следствие.

КонтейнерГлавная осьjustify-*items-*
flexгоризонтальслева направопо вертикали
flex-colвертикальсверху внизпо горизонтали
Мнемоника: justify — «вдоль», items — «поперёк». Перепутали — переверните контейнер flex-col и посмотрите, что изменилось.

justify-start (по умолчанию)

1
2
3

justify-center

1
2
3

justify-between

1
2
3
<div class="space-y-3">
  <p class="text-xs font-medium text-slate-500">justify-start (по умолчанию)</p>
  <div class="flex gap-2 rounded-lg bg-slate-100 p-2">
    <div class="rounded bg-sky-600 px-3 py-2 text-xs text-white">1</div>
    <div class="rounded bg-sky-600 px-3 py-2 text-xs text-white">2</div>
    <div class="rounded bg-sky-600 px-3 py-2 text-xs text-white">3</div>
  </div>
  <p class="text-xs font-medium text-slate-500">justify-center</p>
  <div class="flex justify-center gap-2 rounded-lg bg-slate-100 p-2">
    <div class="rounded bg-sky-600 px-3 py-2 text-xs text-white">1</div>
    <div class="rounded bg-sky-600 px-3 py-2 text-xs text-white">2</div>
    <div class="rounded bg-sky-600 px-3 py-2 text-xs text-white">3</div>
  </div>
  <p class="text-xs font-medium text-slate-500">justify-between</p>
  <div class="flex justify-between gap-2 rounded-lg bg-slate-100 p-2">
    <div class="rounded bg-sky-600 px-3 py-2 text-xs text-white">1</div>
    <div class="rounded bg-sky-600 px-3 py-2 text-xs text-white">2</div>
    <div class="rounded bg-sky-600 px-3 py-2 text-xs text-white">3</div>
  </div>
</div>

Представьте полку с книгами. justify-* решает, где книги стоят вдоль полки: слева, по центру, вплотную к краям. items-* решает, как они выровнены по высоте: по нижнему краю, по центру, растянуты до самого верха. Поворот полки на бок — это и есть flex-col.

Выравнивание поперёк

items-start · items-center · items-stretch

start
выше
center
выше
stretch
оба на всю высоту
<div class="space-y-3">
  <p class="text-xs font-medium text-slate-500">items-start · items-center · items-stretch</p>
  <div class="flex h-24 items-start gap-2 rounded-lg bg-slate-100 p-2">
    <div class="rounded bg-emerald-600 px-3 py-2 text-xs text-white">start</div>
    <div class="rounded bg-emerald-600 px-3 py-4 text-xs text-white">выше</div>
  </div>
  <div class="flex h-24 items-center gap-2 rounded-lg bg-slate-100 p-2">
    <div class="rounded bg-emerald-600 px-3 py-2 text-xs text-white">center</div>
    <div class="rounded bg-emerald-600 px-3 py-4 text-xs text-white">выше</div>
  </div>
  <div class="flex h-24 items-stretch gap-2 rounded-lg bg-slate-100 p-2">
    <div class="rounded bg-emerald-600 px-3 py-2 text-xs text-white">stretch</div>
    <div class="rounded bg-emerald-600 px-3 py-2 text-xs text-white">оба на всю высоту</div>
  </div>
</div>

Рост и сжатие: flex-1, shrink-0, basis

Три класса решают почти все задачи распределения места:

  • flex-1 — «занять всё свободное место», можно нескольким элементам сразу — они поделят место поровну;
  • shrink-0 — «не сжимайся», обязателен для иконок и аватаров;
  • basis-* — стартовый размер до распределения остатка.
shrink-0
flex-1 — забирает остаток
shrink-0
<div class="flex gap-2 rounded-lg bg-slate-100 p-2">
  <div class="shrink-0 rounded bg-slate-700 px-3 py-2 text-xs text-white">shrink-0</div>
  <div class="flex-1 rounded bg-violet-600 px-3 py-2 text-xs text-white">flex-1 — забирает остаток</div>
  <div class="shrink-0 rounded bg-slate-700 px-3 py-2 text-xs text-white">shrink-0</div>
</div>

Почему не w-full? Потому что w-full — это «100% родителя», и во flex-строке такой элемент выдавит соседей. flex-1 считает именно оставшееся место.

min-w-0: почему текст «распирает» строку

По умолчанию flex-элемент не может стать меньше своего содержимого (min-width: auto). Длинное слово или ссылка «распирают» строку, и truncate не срабатывает. Лечение — min-w-0:

Без min-w-0: оченьдлинноеназваниефайлакотороенепомещается.pdf

С min-w-0: оченьдлинноеназваниефайлакотороенепомещается.pdf

<div class="space-y-3">
  <div class="flex max-w-sm gap-3 rounded-lg border border-slate-200 p-3">
    <div class="size-9 shrink-0 rounded-full bg-rose-200"></div>
    <p class="truncate text-sm text-slate-700">Без min-w-0: оченьдлинноеназваниефайлакотороенепомещается.pdf</p>
  </div>
  <div class="flex max-w-sm gap-3 rounded-lg border border-slate-200 p-3">
    <div class="size-9 shrink-0 rounded-full bg-emerald-200"></div>
    <p class="min-w-0 truncate text-sm text-slate-700">С min-w-0: оченьдлинноеназваниефайлакотороенепомещается.pdf</p>
  </div>
</div>

Перенос строк

flex-wrap разрешает элементам переходить на следующую строку. Это простейший способ сделать раскладку адаптивной без медиазапросов:

дизайн вёрстка типографика доступность адаптивность анимация
<div class="flex flex-wrap gap-2">
  <span class="rounded-full bg-slate-200 px-3 py-1 text-xs text-slate-700">дизайн</span>
  <span class="rounded-full bg-slate-200 px-3 py-1 text-xs text-slate-700">вёрстка</span>
  <span class="rounded-full bg-slate-200 px-3 py-1 text-xs text-slate-700">типографика</span>
  <span class="rounded-full bg-slate-200 px-3 py-1 text-xs text-slate-700">доступность</span>
  <span class="rounded-full bg-slate-200 px-3 py-1 text-xs text-slate-700">адаптивность</span>
  <span class="rounded-full bg-slate-200 px-3 py-1 text-xs text-slate-700">анимация</span>
</div>

Центрирование двумя классами

Классическая задача «центрировать по вертикали и горизонтали» решается так:

flex items-center justify-center
<div class="flex h-32 items-center justify-center rounded-lg border border-dashed border-slate-300">
  <span class="rounded-md bg-slate-900 px-4 py-2 text-sm text-white">flex items-center justify-center</span>
</div>

Когда flex, а когда grid

ЗадачаИнструмент
Ряд элементов, размеры зависят от содержимогоFlexbox
Шапка: слева логотип, справа кнопкиFlexbox
Сетка карточек с равными колонкамиGrid
Раскладка страницы: сайдбар + контентGrid
Выравнивание пары «иконка + текст»Flexbox

Коротко: flex — про одну ось, grid — про две. Подробное сравнение будет в уроке 09.