CSS Grid на практике: три макета, которые верстают чаще всего
Разбираем три реальных макета — карточки товаров, holy grail и панель дашборда — на чистом CSS Grid. С рабочей разметкой, которую можно скопировать и запустить.

Grid поддерживается всеми актуальными браузерами больше пяти лет, но большинство верстальщиков используют из него две-три конструкции и снова тянутся к флексбоксу. Ниже — три макета, которые встречаются почти в каждом проекте: адаптивная сетка карточек, классический «святой Грааль» и панель дашборда с шапкой и сайдбаром. Всё на чистом CSS Grid, без медиазапросов там, где без них можно обойтись. Разметка рабочая — копируйте в файл и открывайте в браузере.
Что нужно знать до начала
Материал рассчитан на того, кто уже писал HTML и CSS, знает, что такое display: flex, но с гридом на «вы». Никаких сборщиков и препроцессоров: обычный .html-файл и любой браузер не старше 2020 года. Всё описанное работает в Chrome, Firefox и Safari текущих версий. Единственная конструкция, которая появилась позже остальных — свойство gap для флексбокса — здесь не используется, так что за совместимость можно не переживать.
Одна вещь путает новичков сильнее прочего: грид работает с двумя осями сразу. Флексбокс раскладывает элементы вдоль одной линии, а перенос на новую строку — побочный эффект. Грид сначала рисует сетку из строк и столбцов, а потом расставляет элементы по ячейкам. Из-за этого мышление другое: вы описываете не поток, а таблицу без таблицы.
Флексбокс отвечает на вопрос «как разложить элементы в ряд». Грид отвечает на вопрос «какую сетку я хочу и куда попадут элементы». Если у макета есть и строки, и столбцы одновременно — это задача для грида.
Макет 1: адаптивная сетка карточек
Классика для каталога товаров или блога: карточки заполняют ширину, а их количество в ряду меняется само при сужении экрана — без единого медиазапроса. Секрет в связке repeat(), auto-fit и функции minmax().
<!-- HTML -->
<div class="cards">
<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>
/* CSS */
.cards {
display: grid;
/* колонки минимум 240px, но растягиваются до равной доли свободного места */
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
gap: 16px;
}
.card {
padding: 24px;
background: #f4f4f5;
border-radius: 8px;
}
Проверка: откройте страницу и потяните за угол окна. Карточки должны сами перестраиваться из четырёх в ряд в три, потом в две и в одну — момент перестройки наступает, когда очередной колонке перестаёт хватать 240 пикселей.
Разберём, что делает каждая часть строки repeat(auto-fit, minmax(240px, 1fr)):
minmax(240px, 1fr)— колонка не уже 240px и не шире равной доли свободного места;auto-fit— браузер создаёт столько колонок, сколько влезет, и растягивает существующие на всю ширину;- если заменить
auto-fitнаauto-fill, лишние пустые колонки останутся, и последняя карточка не растянется на всю строку. Для каталога почти всегда нуженauto-fit.
Макет 2: святой Грааль — шапка, три колонки, подвал
Шапка сверху, подвал снизу, между ними сайдбар слева, основной контент по центру и второй сайдбар справа. До грида такое верстали костылями с float и отрицательными отступами. Теперь — областями.
<!-- HTML -->
<div class="layout">
<header>Шапка</header>
<nav>Меню</nav>
<main>Контент</main>
<aside>Виджеты</aside>
<footer>Подвал</footer>
</div>
/* CSS */
.layout {
display: grid;
min-height: 100vh;
grid-template-columns: 200px 1fr 200px;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header header"
"nav main aside"
"footer footer footer";
gap: 12px;
}
.layout header { grid-area: header; }
.layout nav { grid-area: nav; }
.layout main { grid-area: main; }
.layout aside { grid-area: aside; }
.layout footer { grid-area: footer; }
Проверка: шапка и подвал должны тянуться на всю ширину, а средняя строка — делиться на три колонки. Средняя строка растёт до высоты экрана за счёт 1fr в grid-template-rows, поэтому подвал прижат к низу даже при коротком контенте.
Именованные области* удобны тем, что макет читается прямо в CSS: строки grid-template-areas — это буквально картинка вашей сетки. Переставить сайдбар на другую сторону — вопрос перестановки слов в этих строках, а не переписывания HTML.
Чтобы на телефоне колонки схлопнулись в одну, добавьте медиазапрос — здесь он оправдан, потому что три колонки по 200px на узком экране бессмысленны:
@media (max-width: 640px) {
.layout {
grid-template-columns: 1fr;
grid-template-areas:
"header"
"nav"
"main"
"aside"
"footer";
}
}
Макет 3: панель дашборда с фиксированным сайдбаром
Отличие от «святого Грааля» — сайдбар и шапка не скроллятся, а прокручивается только область контента. Сетка задаёт каркас, а прокрутку берёт на себя внутренний блок.
<!-- HTML -->
<div class="dashboard">
<aside class="sidebar">Навигация</aside>
<header class="topbar">Заголовок</header>
<main class="content">Основной контент</main>
</div>
/* CSS */
.dashboard {
display: grid;
height: 100vh;
grid-template-columns: 240px 1fr;
grid-template-rows: 56px 1fr;
grid-template-areas:
"sidebar topbar"
"sidebar content";
}
.dashboard .sidebar { grid-area: sidebar; overflow-y: auto; }
.dashboard .topbar { grid-area: topbar; }
.dashboard .content {
grid-area: content;
overflow-y: auto; /* скроллится только контент, каркас на месте */
}
Проверка: добавьте в .content много абзацев. Прокручиваться должен только он — сайдбар и шапка остаются на месте. Если скроллится вся страница, проверьте, что у .dashboard задана height: 100vh, а не min-height.
Когда grid, когда flex
| Задача | Инструмент | Почему |
|---|---|---|
| Ряд кнопок, теги, элементы в строку | flex | одна ось, перенос по потоку |
| Сетка карточек с равными колонками | grid | две оси, колонки должны совпадать |
| Каркас страницы (шапка/сайдбар/подвал) | grid | области именуются, легко перекраивать |
| Центрирование одного блока | любой | обе технологии умеют, разницы нет |
| Выравнивание по базовой линии текста | flex | у grid нет baseline-выравнивания между строками |
Если не получилось
- Карточки не переносятся, лезут в одну строку. Проверьте, что не написали
grid-auto-flow: columnи что у контейнера действительноdisplay: grid, а неinline-gridс фиксированной шириной. - Элемент не встал в свою область. Имя в
grid-areaдолжно точно совпадать со словом вgrid-template-areas, без кавычек и с учётом регистра. Опечатка в имени — самая частая причина. - Пустая ячейка вместо элемента. В
grid-template-areasодну и ту же область нужно указывать смежными ячейками — они должны образовывать прямоугольник. Разрыв области браузер молча игнорирует. - Колонка
1frраздулась шире экрана. Единицаfrсчитает свободное место, но не учитывает минимальный размер контента вроде длинного слова или широкой картинки. Добавьте элементуmin-width: 0илиoverflow: hidden. - Grid не работает в старом браузере. Если нужна поддержка Internet Explorer 11 — там реализован устаревший синтаксис 2011 года (
-ms-grid) безgapиauto-fit. Проще отдать таким браузерам простой линейный fallback, чем поддерживать два синтаксиса.
Что настроить дальше
Три макета выше закрывают большинство типовых задач. Следующие шаги, когда освоите каркасы:
- изучите
grid-column: span 2иgrid-row: span 2— так карточка занимает несколько ячеек, это база для плиточных «masonry-подобных» раскладок; - посмотрите свойства выравнивания
justify-items,align-items,place-content— они управляют содержимым ячеек и самой сеткой; - откройте панель Grid в DevTools (в Chrome и Firefox она подсвечивает линии и номера дорожек) — это ускоряет отладку в разы;
- функция
subgridпозволяет дочерней сетке наследовать дорожки родителя; поддержка появилась относительно недавно, перед использованием сверьте её в актуальной таблице совместимости на MDN.
Инвалидация классов и БЭМ-именование — отдельная тема, здесь рассматриваем только раскладку.
Карточки для маркетплейсов: Таблица товаров и папка фотографий на входе — комплект слайдов и описаний на выходе, по требованиям Wildberries и Ozon.
Спросить за 5 ₽Источники: MDN — CSS Grid Layout, CSS Grid Layout Module Level 1 (W3C)
Частые вопросы
А если мне нужна поддержка старых браузеров?
Карточки перестраиваются, но последняя не растягивается на всю строку. Что не так?
Grid заменяет флексбокс полностью?
Можно ли делать masonry-раскладку (как в Pinterest) на чистом Grid?
Почему колонка 1fr вылезает за пределыконтейнера?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.