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?