Flexbox vs Grid

Flexbox — одномерная система раскладки (строка ИЛИ столбец). Grid — двумерная (строки И столбцы одновременно). Они не конкуренты, а дополняют друг друга.

Зачем нужно

Выбор между Flexbox и Grid — один из самых частых вопросов при вёрстке. Понимание сильных сторон каждого инструмента позволяет выбрать оптимальный подход и комбинировать их.

Где используется

  • Flexbox: навигация, панели инструментов, карточки, центрирование, распределение элементов в ряд
  • Grid: макеты страниц, карточные сетки, дашборды, формы, сложные двумерные раскладки

Предпосылки

Сравнительная таблица

Характеристика Flexbox Grid
Размерность 1D (строка или столбец) 2D (строки и столбцы)
Подход Контент определяет раскладку Раскладка определяет размещение
Оси Главная + поперечная inline + block
Wrapping flex-wrap Автоматически через треки
Именованные области Нет grid-template-areas
Gap gap gap
Выравнивание justify-content, align-items + justify-items, place-*
Перекрытие элементов Нет (без position) Да (элементы могут наложиться)
Subgrid Нет Да

Когда использовать Flexbox

1. Однонаправленный поток

/* Навигация */
.nav {
  display: flex;
  gap: 16px;
  align-items: center;
}

/* Панель кнопок */
.toolbar {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

2. Контент определяет размер

/* Теги — каждый по ширине содержимого */
.tags {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.tag {
  padding: 4px 12px;
  background: #e9ecef;
  border-radius: 16px;
  /* Ширина = по содержимому */
}

3. Распределение пространства

/* Sidebar + Content */
.layout {
  display: flex;
}

.sidebar {
  flex: 0 0 250px; /* Фиксированный */
}

.content {
  flex: 1; /* Занимает всё оставшееся */
}

4. Центрирование

/* Идеальное центрирование */
.center {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100dvh;
}

Когда использовать Grid

1. Двумерный макет

/* Макет страницы */
.page {
  display: grid;
  grid-template-columns: 250px 1fr;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "header header"
    "sidebar content"
    "footer footer";
}

2. Сетка одинаковых элементов

/* Галерея / каталог */
.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 16px;
}

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

/* Форма */
.form {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 12px 16px;
  align-items: center;
}

/* label и input автоматически в двух колонках */

4. Наложение элементов

/* Карточка с изображением и текстом поверх */
.hero-card {
  display: grid;
}

.hero-card img,
.hero-card .overlay {
  grid-area: 1 / 1; /* Оба в одной ячейке — наложение */
}

.hero-card .overlay {
  align-self: end;
  background: linear-gradient(transparent, rgba(0,0,0,0.8));
  color: white;
  padding: 20px;
}

Комбинация Flexbox + Grid

Они прекрасно работают вместе:

/* Grid для макета страницы */
.page {
  display: grid;
  grid-template-columns: 250px 1fr;
  grid-template-rows: auto 1fr auto;
}

/* Flex для навигации внутри header */
.header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 24px;
}

/* Grid для сетки карточек в content */
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 20px;
}

/* Flex внутри карточки */
.card {
  display: flex;
  flex-direction: column;
}

.card-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: auto; /* Прижать к низу */
}

Правило выбора

Нужно ли контролировать СТРОКИ и СТОЛБЦЫ одновременно?
│
├─ Да → Grid
│   ├─ Макет страницы → grid-template-areas
│   ├─ Сетка карточек → repeat(auto-fill, minmax)
│   └─ Форма → grid с колонками
│
└─ Нет, только в ОДНОМ направлении → Flexbox
    ├─ Навигация → flex + gap
    ├─ Кнопки в ряд → flex + gap
    ├─ Центрирование → flex + justify/align
    └─ Sidebar + Content → flex + flex:1

Простое правило: Grid — для макета, Flexbox — для компонентов. Но это не строгое правило, а отправная точка.

Частые ошибки

  1. Использование Grid для одномерных задач — навигация из 5 ссылок не нуждается в Grid
  2. Использование Flexbox для двумерной сеткиflex-wrap не гарантирует выравнивание по колонкам:
    /* ПЛОХО — последний ряд может быть неровным */
    .cards { display: flex; flex-wrap: wrap; }
    .card { width: calc(33.333% - 20px); }
    
    /* ХОРОШО */
    .cards {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
    }
    
  3. Боязнь комбинировать — Grid и Flexbox отлично работают вместе
  4. Grid для простого центрирования — и Grid, и Flexbox подходят, оба варианта валидны

Практика

  • Создать навигацию через Flexbox
  • Создать ту же навигацию через Grid — сравнить
  • Сделать макет страницы на Grid с Flexbox-навигацией внутри
  • Реализовать карточную сетку: Grid для раскладки, Flex внутри карточек
  • Попробовать наложение элементов в Grid (невозможно в Flexbox без position)

Связанные темы

Ресурсы