Responsive Grid без media queries

Паттерн адаптивной Grid-раскладки, при котором количество колонок автоматически изменяется в зависимости от ширины контейнера без единого медиазапроса — через сочетание repeat, auto-fill/auto-fit и minmax.

Зачем нужно

Медиазапросы привязаны к размеру вьюпорта, но компонент может находиться в любом контейнере разной ширины. Адаптивная сетка без медиазапросов работает корректно вне зависимости от контекста — в сайдбаре, в модалке или на полной ширине. Это делает компонент truly reusable.

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

  • Карточные галереи с динамическим числом элементов
  • Сетки товаров в интернет-магазинах
  • Фотогалереи
  • Адаптивные дашборды

Паттерн RAM (Repeat, Auto, Minmax)

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 20px;
}
<div class="grid">
  <div class="card">Карточка 1</div>
  <div class="card">Карточка 2</div>
  <div class="card">Карточка 3</div>
  <div class="card">Карточка 4</div>
  <div class="card">Карточка 5</div>
</div>

При ширине контейнера 1000px — 4 колонки по ~250px. При 600px — 2 колонки. При 280px — 1 колонка.

auto-fill vs auto-fit

/* auto-fill: создаёт столько треков, сколько поместится */
/* Если элементов меньше чем треков — пустые треки сохраняются */
.fill {
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}

/* auto-fit: пустые треки схлопываются до 0 */
/* Элементы растягиваются на всю ширину контейнера */
.fit {
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}

Разница заметна когда элементов мало:

  • auto-fill: три элемента в трёх первых колонках, остальное — пустота
  • auto-fit: три элемента растягиваются на всю ширину

Продвинутый вариант: ограничение максимума колонок

/* Максимум 4 колонки — минимум 1 */
.grid {
  --min-col: 200px;
  --max-cols: 4;
  
  display: grid;
  grid-template-columns: repeat(
    auto-fill,
    minmax(min(var(--min-col), 100%), 1fr)
  );
  gap: 16px;
}

Адаптивные строки

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  grid-auto-rows: minmax(200px, auto); /* строки не ниже 200px */
  gap: 20px;
}

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

  1. minmax(200px, 1fr) при узком контейнере — если контейнер уже 200px, колонка выходит за границу; используйте minmax(min(200px, 100%), 1fr).
  2. auto-fit с одним элементом — единственный элемент растянется на всю ширину; это не всегда желаемое поведение.
  3. Нет gap — карточки слипаются; всегда задавайте gap.

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

Ресурсы