Урок по треку HTML и CSS 7 мин

CSS Grid за 7 минут

Треки, fr, minmax, auto-fit и auto-fill, области, неявная сетка и subgrid.

Grid раскладывает элементы сразу по двум осям: строкам и колонкам. Flexbox думает одной линией, Grid думает таблицей. Если макет задаётся «сеткой сверху» (каркас страницы, галерея, форма в две колонки), берите Grid. Если элементы просто выстраиваются в ряд и делят место по содержимому, хватит Flexbox.

Контейнер и треки

.layout {
  display: grid;
  grid-template-columns: 200px 1fr 1fr;
  grid-template-rows: auto 1fr auto;
  gap: 16px;
}
  • Трек - это колонка или строка. Линии - границы между треками, нумеруются с 1, а с конца с -1.
  • fr - доля свободного места, которое осталось после фиксированных треков и gap. 1fr 2fr делит остаток как 1:2.
  • gap задаёт промежутки только между треками, не по краям.

Важная деталь: 1fr на самом деле значит minmax(auto, 1fr). Минимум auto не даёт колонке стать уже самого длинного слова или широкой картинки. Отсюда классический баг: длинная строка без пробелов распирает колонку. Лечится minmax(0, 1fr) или min-width: 0 у элемента.

repeat, minmax, auto-fit и auto-fill

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 24px;
}

Это адаптивная сетка карточек без медиазапросов: браузер сам решает, сколько колонок шириной от 220px помещается.

  • auto-fill создаёт столько колонок, сколько влезет, даже пустые. Если карточек мало, справа остаются пустые треки.
  • auto-fit делает то же, но схлопывает пустые треки до нуля, и реальные карточки растягиваются на всю ширину.

Разница видна только когда элементов меньше, чем помещается колонок.

Размещение элементов

.header { grid-column: 1 / -1; }        /* от первой до последней линии */
.sidebar { grid-row: 2 / 4; }           /* занять строки 2 и 3 */
.wide { grid-column: span 2; }          /* растянуться на 2 колонки */

grid-column: 1 / -1 растягивает элемент на всю ширину явной сетки. Конечная линия не входит в «занятые» ячейки: 2 / 4 - это две строки.

Именованные области

.page {
  display: grid;
  grid-template-columns: 240px 1fr;
  grid-template-areas:
    "header header"
    "nav    main"
    "footer footer";
}
.page > header { grid-area: header; }
.page > nav    { grid-area: nav; }

Области должны быть прямоугольными, иначе всё свойство считается невалидным. Точка . в шаблоне означает пустую ячейку. На мобильном достаточно переписать grid-template-areas в медиазапросе, разметка не меняется.

Явная и неявная сетка

Всё, что вы описали в grid-template-*, это явная сетка. Если элементов больше, браузер создаёт новые строки сам: это неявная сетка. Их размер задаёт grid-auto-rows (по умолчанию auto), а направление автоматического размещения задаёт grid-auto-flow (row по умолчанию, можно column). Значение dense разрешает заполнять дырки элементами из конца списка, но тогда визуальный порядок расходится с порядком в DOM, что плохо для клавиатуры и скринридера.

Выравнивание

  • justify-items / align-items - выравнивание элементов внутри своих ячеек по строчной и блочной оси.
  • justify-content / align-content - выравнивание всей сетки внутри контейнера, если треки меньше контейнера.
  • place-items: center - сокращение для обоих *-items. Самый короткий способ отцентрировать:
.center { display: grid; place-items: center; }

subgrid

Проблема: в ряду карточек заголовки разной длины, и кнопки «Купить» оказываются на разной высоте. Каждая карточка - своя сетка, они не знают друг о друге. subgrid позволяет вложенной сетке взять треки родителя:

.cards { display: grid; grid-template-columns: repeat(3, 1fr); }
.card {
  display: grid;
  grid-row: span 3;               /* карточка занимает 3 строки родителя */
  grid-template-rows: subgrid;    /* и использует их как свои */
}

Теперь строки «картинка / заголовок / кнопка» общие для всех карточек ряда. subgrid поддерживается во всех основных браузерах с 2023 года.

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

  • Ждать, что gap добавит отступ по краям контейнера. Не добавит, нужен padding.
  • Путать auto-fill и auto-fit и удивляться, почему одна карточка не растянулась.
  • Не учесть min-width: auto у 1fr и получить горизонтальный скролл от длинного URL.
  • Нарушить порядок чтения через order, dense или размещение по линиям.

Что спросят на собесе

  • Когда Grid, а когда Flexbox? Grid для двумерного каркаса, Flexbox для одномерного ряда.
  • Что такое fr и почему колонка 1fr может не сжаться?
  • Чем auto-fill отличается от auto-fit?
  • Как сделать адаптивную сетку карточек без медиазапросов?
  • Что такое неявная сетка и subgrid?

Закрепите за 5 минут

После урока в тренажёре 3-5 проверочных вопросов, дальше модуль уходит в повторения.