Flexbox vs Grid: когда использовать каждый инструмент вёрстки
Сравниваем два главных инструмента CSS-раскладки на живых примерах и объясняем, какой подход выбрать для конкретных задач. Разбираем типичные ошибки, из-за которых верстка «ломается» на мобильных.
Содержание
Flexbox vs Grid: когда использовать каждый инструмент вёрстки
Среди разработчиков до сих пор нет единого мнения о том, что выбрать — Flexbox или CSS Grid. Одни говорят, что Grid вытеснил Flexbox и теперь он не нужен. Другие верстают всё подряд через flex, потому что «так привычнее». Оба подхода ошибочны, и оба приводят к одному результату: верстке, которая ломается на мобильных, требует костылей и плохо читается другими разработчиками.
Правда в том, что Flexbox и Grid решают разные задачи. Они не конкурируют — они дополняют друг друга. Разобраться в этом различии — значит перестать бороться с CSS и начать думать на его языке.
Откуда вообще взялась путаница
До появления Flexbox (2012) и Grid (2017) разработчики верстали раскладки через float, inline-block и таблицы. Это было неудобно, ненадёжно и требовало огромного количества хаков. Когда Flexbox появился в браузерах, он стал настоящим спасением — и многие просто начали использовать его везде, для любых задач.
Grid появился позже и поначалу воспринимался как «что-то сложное для сеток». Постепенно поддержка браузеров выровнялась, и сегодня оба инструмента доступны без каких-либо полифилов. Но привычка «всё на флексах» никуда не делась.
Чтобы понять, когда что использовать, нужно вернуться к базовому вопросу: что именно ты раскладываешь?
Одно измерение против двух
Ключевое различие между Flexbox и Grid — это количество осей, с которыми они работают.
Flexbox — это одномерная система. Ты выстраиваешь элементы либо в строку, либо в колонку. Да, элементы могут переноситься на новую строку через flex-wrap, но каждая строка при этом живёт независимо — Flexbox не знает ничего о соседних строках.
Grid — двумерная система. Ты явно задаёшь строки и колонки, и элементы размещаются в пересечении этих осей. Grid «видит» всю раскладку целиком.
Это звучит абстрактно, поэтому разберём на конкретных примерах.
Когда использовать Flexbox
Навигация и горизонтальные списки
Классический случай — шапка сайта с логотипом слева и меню справа. Это типичная одномерная задача: выстроить элементы в строку и распределить пространство между ними.
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 24px;
}
Здесь Grid был бы избыточен. Нам не нужны строки — только одна ось и контроль над выравниванием.
Карточки с переменным содержимым
Допустим, у тебя есть карточка товара: картинка, заголовок, описание и кнопка «Купить». Нужно, чтобы кнопка всегда прижималась к низу карточки, независимо от длины текста.
.card {
display: flex;
flex-direction: column;
height: 100%;
}
.card__body {
flex: 1; /* занимает всё доступное пространство */
}
.card__button {
margin-top: auto;
}
Это задача для Flexbox: управление распределением пространства внутри одного элемента по одной оси.
Центрирование элементов
Один из самых частых запросов — «как отцентрировать блок по вертикали и горизонтали». Flexbox справляется с этим в две строки:
.container {
display: flex;
justify-content: center;
align-items: center;
}
Простая задача — простое решение.
Динамические компоненты с неизвестным числом элементов
Если количество элементов заранее неизвестно (теги, чипы, список фильтров), Flexbox с flex-wrap — правильный выбор. Элементы сами перенесутся на новую строку, когда закончится место.
.tags {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
Когда использовать Grid
Раскладка страницы целиком
Если нужно разбить страницу на шапку, боковую панель, основной контент и подвал — это задача для Grid. Ты явно описываешь структуру, и браузер строго её соблюдает.
.page {
display: grid;
grid-template-columns: 240px 1fr;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header"
"sidebar content"
"footer footer";
min-height: 100vh;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.content { grid-area: content; }
.footer { grid-area: footer; }
Попробуй сделать то же самое на Flexbox — и ты быстро обнаружишь, что тебе нужны вложенные контейнеры, дополнительные обёртки и масса компромиссов.
Сетки карточек
Галереи, каталоги товаров, плитки — всё, где нужно выровнять элементы и по горизонтали, и по вертикали одновременно.
.catalog {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 24px;
}
Одна строка — и ты получаешь адаптивную сетку, которая сама решает, сколько колонок поместится. Никаких медиазапросов для базового поведения.
Сложные дашборды и интерфейсы
Когда элементы должны занимать несколько строк или колонок, Grid незаменим:
.dashboard {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 16px;
}
.widget--wide {
grid-column: span 2;
}
.widget--tall {
grid-row: span 2;
}
Это невозможно выразить через Flexbox без значительных усложнений.
Типичные ошибки, из-за которых верстка ломается на мобильных
Здесь стоит остановиться подробнее — именно эти ошибки чаще всего встречаются у разработчиков, которые только осваивают раскладки.
Ошибка 1: фиксированные размеры вместо гибких единиц
/* Плохо */
.grid {
display: grid;
grid-template-columns: 300px 300px 300px;
}
/* Хорошо */
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
На экране шириной 320px три колонки по 300px дадут горизонтальный скролл. 1fr — дробная единица, которая делит доступное пространство, а не задаёт абсолютный размер.
Ошибка 2: забытый min-width: 0 у flex-элементов
Flex-элементы по умолчанию не могут быть меньше размера своего содержимого. Это приводит к переполнению контейнера длинными словами или URL.
/* Текст внутри может вылезти за пределы */
.flex-item {
flex: 1;
}
/* Правильно */
.flex-item {
flex: 1;
min-width: 0;
}
Это одна из самых неочевидных проблем Flexbox, и она регулярно ломает верстку на мобильных.
Ошибка 3: flex-wrap без учёта минимальной ширины
.container {
display: flex;
flex-wrap: wrap;
}
.item {
flex: 1 1 200px; /* хочу перенос при ширине меньше 200px */
}
Выглядит логично, но если у item есть padding или border, а box-sizing не установлен в border-box — реальный размер окажется больше 200px, и перенос произойдёт не там, где ожидалось. Всегда добавляй в сброс стилей:
*, *::before, *::after {
box-sizing: border-box;
}
Ошибка 4: Grid без адаптации под мобильные
/* Только для десктопа */
.grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
}
На мобильном четыре колонки превратятся в узкие полоски. Используй auto-fill или auto-fit с minmax, либо явно переопределяй шаблон в медиазапросе:
.grid {
display: grid;
grid-template-columns: 1fr; /* мобильный — одна колонка */
}
@media (min-width: 768px) {
.grid {
grid-template-columns: repeat(2, 1fr);
}
}
@media (min-width: 1200px) {
.grid {
grid-template-columns: repeat(4, 1fr);
}
}
Ошибка 5: вложенные флексы вместо Grid
Когда разработчик пытается построить двумерную раскладку через Flexbox, он неизбежно приходит к вложенным контейнерам. Это усложняет HTML, создаёт проблемы с выравниванием строк и делает код хрупким.
<!-- Антипаттерн: имитация Grid через вложенные flex -->
<div class="row">
<div class="col">...</div>
<div class="col">...</div>
</div>
<div class="row">
<div class="col">...</div>
<div class="col">...</div>
</div>
Если тебе нужна сетка — используй Grid. Это именно то, для чего он создан.
Можно ли комбинировать Flexbox и Grid?
Не только можно — нужно. В реальных проектах они работают вместе на разных уровнях.
Типичная схема: Grid задаёт общую раскладку страницы или крупных блоков, а Flexbox управляет содержимым внутри этих блоков — выравниванием элементов в карточке, распределением иконок в кнопке, навигационными ссылками в шапке.
/* Grid — структура страницы */
.layout {
display: grid;
grid-template-columns: 1fr 3fr;
gap: 32px;
}
/* Flexbox — содержимое карточки внутри grid-ячейки */
.card {
display: flex;
flex-direction: column;
gap: 12px;
}
Именно такой подход используется в большинстве современных дизайн-систем и компонентных библиотек.
Практический ориентир: как принять решение
Вот простой алгоритм, который помогает сделать выбор:
- Один ряд или один столбец → Flexbox
- Сетка, таблица, двумерная раскладка → Grid
- Неизвестное количество элементов, которые должны переноситься → Flexbox с
flex-wrap - Элементы должны выравниваться относительно друг друга по двум осям → Grid
- Нужно управлять пространством внутри компонента → Flexbox
- Нужно задать структуру всей страницы или крупного раздела → Grid
Если сомневаешься — задай себе вопрос: «Мне важно, как элементы выстраиваются относительно соседних строк?» Если да — Grid. Если нет — Flexbox.
Тем, кто хочет разобраться в этих инструментах системно, а не через разрозненные примеры из Stack Overflow, может быть полезен курс «HTML/CSS» — там раскладки разбираются в контексте реальной вёрстки, от базовых концепций до адаптивных компонентов.
Вывод
Flexbox и Grid — не конкуренты и не замена друг другу. Это два инструмента с разными зонами ответственности. Flexbox отлично справляется с одномерными задачами: выравниванием, распределением пространства внутри строки или колонки, управлением компонентами с переменным содержимым. Grid берёт на себя двумерные раскладки: структуру страниц, сетки карточек, сложные интерфейсы.
Большинство проблем с мобильной версткой — это не баги браузеров и не недостатки CSS. Это следствие применения инструмента не по назначению: попытки построить двумерную сетку через Flexbox, использования фиксированных размеров там, где нужны гибкие единицы, или игнорирования box-sizing.
Когда понимаешь, что именно ты раскладываешь и по скольким осям — выбор между Flexbox и Grid становится очевидным. Если хочется углубиться в тему и выстроить понимание с нуля, курс «HTML/CSS» — один из разумных способов это сделать структурированно, а не методом проб и ошибок.
Комментарии
Пока нет комментариев