CSS Grid - режим CSS для двумерной раскладки: в отличие от Flexbox, который управляет только одним направлением за раз, Grid управляет строками и колонками ОДНОВРЕМЕННО в одном контейнере. Достаточно свойства display: grid на родителе и grid-template-columns, чтобы задать сетку, - и её прямые потомки сами распределятся по ячейкам.
В этом уроке
Попробуй прямо сейчас: замени grid-template-columns на "1fr 1fr 1fr 1fr" - вместо 3 колонок и 2 строк из 6 элементов получится 4 колонки и уже другое число строк, при этом ни один элемент трогать не пришлось.
Зачем нужен CSS Grid: какую проблему он решает
Flexbox, который разбирался в прошлой группе уроков, работает вдоль ОДНОГО направления - строки или столбца. Чтобы получить настоящую сетку из нескольких строк И столбцов одновременно (например, карточки товаров ровными рядами, где важно выравнивание и по горизонтали, и по вертикали сразу), с Flexbox приходится либо вкладывать один flex-контейнер в другой, либо мириться с тем, что высота строк не связана со столбцами соседних строк. CSS Grid решает именно эту задачу: один-единственный контейнер с display: grid одновременно управляет и строками, и столбцами, а сами элементы автоматически распределяются по получившимся ячейкам.
.grid { display: grid; grid-template-columns: 100px 100px 100px; } - шесть элементов сами выстроятся в 2 строки по 3 колонки.
.outer { display: flex; } .inner { display: flex; } с вложенными друг в друга flex-контейнерами - рабочий, но громоздкий способ имитировать сетку, который Grid делает одним контейнером.
Как включить CSS Grid: контейнер, треки и ячейки
display: grid делает элемент grid-контейнером, и, как и в случае с Flexbox, ТОЛЬКО его прямые потомки становятся grid-элементами. grid-template-columns задаёt количество и ширину колонок сразу одной строкой значений - например, "100px 100px 100px" создаёт три колонки по 100px. Элементы заполняют ячейки слева направо и сверху вниз и сами переходят на новую строку, когда место в текущей заканчивается - без всякого аналога flex-wrap. Если grid-template-rows не задан, высота строк определяется автоматически по высоте содержимого. Отдельного внимания заслуживает единица fr (fraction, "доля") - она есть только у Grid и делит СВОБОДНОЕ место между колонками в заданной пропорции: 1fr 2fr отдаёт второй колонке ровно вдвое больше места, чем первой.
.grid { display: grid; grid-template-columns: 1fr 1fr; } - две равные по ширине колонки, делящие всё свободное место поровну.
.item { display: grid; } на отдельном элементе внутри контейнера - display: grid, как и display: flex, работает только будучи заданным на самом контейнере.
Grid и Flexbox: когда какой инструмент использовать
Общее практическое правило: если нужно управлять расположением элементов только в ОДНОМ направлении (кнопки в шапке сайта, пункты меню в ряд) - подойдёт Flexbox с justify-content и align-items, которые уже разбирались раньше. Если же нужна общая структура страницы сразу по двум направлениям (шапка, сайдбар, основной контент и подвал в одной сетке) - для этого создан Grid. На практике их не выбирают одно вместо другого, а часто сочетают в одном проекте: Grid - для общей раскладки страницы целиком, а внутри одной из её ячеек - обычный flex-контейнер для выравнивания элементов конкретного компонента.
display: grid; grid-template-columns: 200px 1fr; для общей раскладки "сайдбар + контент", и display: flex; внутри самого сайдбара для выравнивания пунктов меню - оба инструмента работают вместе, каждый на своём уровне.
display: grid; ради выравнивания одной строки кнопок - формально сработает, но для одномерной задачи Flexbox обычно проще и привычнее.
Частые ошибки новичков
| Ошибка | Что происходит | Как исправить |
|---|---|---|
| Продолжают вкладывать flex-контейнеры друг в друга для имитации сетки | Код становится громоздким, а строки и столбцы не связаны друг с другом по размеру | Для настоящей двумерной сетки использовать один контейнер с display: grid |
| Пишут display: grid на отдельном элементе внутри контейнера | Свойство не действует так, как ожидалось | display: grid задаётся на родителе, чьи прямые потомки должны стать ячейками сетки |
| Считают, что Grid должен полностью заменить Flexbox в проекте | Одномерные задачи (ряд кнопок) решаются через Grid сложнее, чем нужно | Использовать оба инструмента вместе: Grid - для общей структуры, Flexbox - для отдельных компонентов |
| Забывают, что fr делит только СВОБОДНОЕ место, а не всю ширину контейнера | Расчёт пропорций колонок не совпадает с ожидаемым, если есть колонки с фиксированной шириной | Учитывать, что fr работает с местом, оставшимся после вычета фиксированных колонок |
Шпаргалка
| Что нужно | Как сделать |
|---|---|
| Включить сетку | display: grid; |
| Задать 3 колонки фиксированной ширины | grid-template-columns: 100px 100px 100px; |
| Разделить свободное место в пропорции | grid-template-columns: 1fr 2fr; |
| Кто становится элементом сетки | только прямые потомки контейнера |
| Высота строк без grid-template-rows | автоматически по высоте содержимого |
| Когда выбрать Flexbox, а когда Grid | одно направление - Flexbox; строки и колонки сразу - Grid |
Коротко: отвечаем на вопросы
Заменяет ли CSS Grid Flexbox полностью?
Нет, это разные инструменты для разных задач. Flexbox лучше подходит для расположения элементов вдоль одного направления, а Grid - для двумерной структуры из строк и колонок сразу. На практике их часто сочетают в одном проекте: Grid - для общей раскладки страницы, Flexbox - для выравнивания элементов внутри отдельных компонентов.
Нужны ли сегодня префиксы вроде -ms- для CSS Grid?
Нет, все современные браузеры поддерживают CSS Grid без префиксов уже несколько лет. Префикс -ms- нужен только для очень старых версий Internet Explorer и ранних версий Edge, которые сегодня практического значения не имеют.