CSS Grid на практических макетах: пошаговая инструкция
Соберём три реальных макета на CSS Grid: карточки товаров, шапку сайта и адаптивную галерею. Без фреймворков, чистый CSS, полчаса времени.

За полчаса вы соберёте три рабочих макета на чистом CSS Grid: сетку карточек, которая сама подстраивается под ширину экрана; шапку сайта с логотипом, меню и кнопкой; адаптивную галерею без единого медиазапроса. Всё копируется в один HTML-файл и открывается в браузере. Grid поддерживается всеми актуальными браузерами с 2017 года, отдельных полифилов не нужно.
Что нужно перед началом
- любой браузер актуальной версии — Chrome, Firefox, Safari или Edge;
- текстовый редактор — подойдёт даже «Блокнот», но удобнее VS Code;
- умение создать
.html-файл и открыть его двойным кликом; - знание, что такое
classв HTML и как подключить<style>. Про сам Grid знать заранее ничего не нужно.
Дополнительно откройте в браузере панель разработчика (F12) — во вкладке Elements рядом с элементом, у которого стоит display: grid, появится значок grid. По клику браузер подсветит линии сетки прямо на странице. Это лучший инструмент отладки для этой темы.
Как Grid устроен в двух предложениях
Вы объявляете контейнер сеткой через display: grid, задаёте колонки и строки, а прямые потомки автоматически становятся ячейками. Дальше либо оставляете браузеру раскладывать элементы по порядку, либо расставляете вручную по номерам линий.
Flexbox раскладывает элементы в одну линию — по строке или по колонке. Grid работает сразу в двух измерениях: строки и колонки одновременно. Для карточной сетки это именно то, что нужно.
Шаг 1. Сетка карточек, которая сама переносится
Задача: показать карточки товаров так, чтобы в ряд помещалось столько, сколько влезет, а лишние переносились на новую строку без ручной настройки количества колонок.
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<style>
.cards {
display: grid;
/* колонки шириной минимум 200px, растягиваются до равной доли */
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 16px;
}
.card {
background: #f2f2f2;
padding: 20px;
border-radius: 8px;
}
</style>
</head>
<body>
<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>
</body>
</html>
Разберём ключевую строку. repeat(auto-fill, minmax(200px, 1fr)) означает: создавай столько колонок, сколько поместится, каждая шириной не меньше 200px, но при избытке места пусть растягиваются поровну (1fr — одна доля свободного пространства).
Проверка: откройте файл и меняйте ширину окна. Карточки должны сами перестраиваться — от одной колонки на узком экране до четырёх-пяти на широком. Медиазапросы для этого не понадобились.
auto-fill или auto-fit
Замените auto-fill на auto-fit и посмотрите разницу на широком экране с двумя карточками. auto-fill оставит пустые колонки-«призраки», карточки прижмутся влево. auto-fit схлопнет пустые колонки, и две карточки растянутся на всю ширину. Для галереи чаще нужен auto-fit, для формы с фиксированной шириной ячеек — auto-fill.
Шаг 2. Шапка сайта: логотип, меню, кнопка
Задача: логотип слева, меню по центру растягивается, кнопка справа. Здесь колонки заданы явно, потому что их роли разные.
<style>
.header {
display: grid;
/* лого по контенту, меню тянется, кнопка по контенту */
grid-template-columns: auto 1fr auto;
align-items: center;
gap: 24px;
padding: 16px 24px;
background: #1a1a1a;
color: #fff;
}
.header nav {
display: flex;
gap: 20px;
}
</style>
<header class="header">
<div class="logo">МойСайт</div>
<nav>
<a href="#">Главная</a>
<a href="#">Каталог</a>
<a href="#">Контакты</a>
</nav>
<button>Войти</button>
</header>
grid-template-columns: auto 1fr auto читается как: первая колонка по ширине содержимого, средняя забирает всё свободное место, третья снова по содержимому. align-items: center выравнивает всё по вертикали, чтобы кнопка и логотип не «плавали».
Проверка: логотип и кнопка прижаты к краям, между ними — растянутая зона с меню. При изменении ширины окна крайние блоки на месте, тянется только середина.
Шаг 3. Галерея с крупным первым элементом
Задача: сетка изображений, где первая картинка занимает две колонки и две строки, а остальные — по одной ячейке. Здесь пригодится ручное размещение.
<style>
.gallery {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: 120px;
gap: 8px;
}
.gallery .item {
background: #cdd;
border-radius: 6px;
}
/* первый элемент занимает 2 колонки и 2 строки */
.gallery .item.big {
grid-column: span 2;
grid-row: span 2;
}
</style>
<div class="gallery">
<div class="item big">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
</div>
grid-column: span 2 говорит элементу занять две колонки начиная с его позиции; grid-row: span 2 — две строки. grid-auto-rows: 120px задаёт высоту строк, которые Grid создаёт автоматически под содержимое.
Проверка: первый блок крупный, в левом верхнем углу, остальные аккуратно обтекают его сеткой. Если добавите ещё элементы, они займут свободные ячейки без наложения.
Именованные области: когда номера линий надоели
Для сложного макета — шапка, боковая панель, контент, подвал — удобнее давать зонам имена, а не считать линии.
<style>
.layout {
display: grid;
grid-template-columns: 200px 1fr;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
gap: 12px;
min-height: 100vh;
}
.layout .head { grid-area: header; }
.layout .side { grid-area: sidebar; }
.layout .main { grid-area: main; }
.layout .foot { grid-area: footer; }
</style>
Строки в grid-template-areas рисуют макет прямо в коде — визуально видно, что где стоит. Каждая зона привязывается к элементу через grid-area. Чтобы переставить сайдбар вправо на мобильном, достаточно переписать области внутри медиазапроса, не трогая HTML.
Если не получилось
- Карточки не переносятся, идут в одну строку. Скорее всего
display: gridстоит не на том элементе. Сеткой должен быть родитель карточек, а не сама карточка. Проверьте в панели разработчика значокgrid— он должен быть у контейнера. - gap не работает. Проверьте, что свойство стоит на grid-контейнере, а не на дочернем элементе. Старое свойство
grid-gapтоже работает, но лучше использовать современноеgap. - Элемент с span вылезает за сетку или ломает раскладку. Значение span больше числа колонок. Если колонок четыре, а вы просите
span 5, браузер добавит колонку и раскладка «поедет». Уменьшите span или увеличьте число колонок. - Пустые «дыры» в сетке. Grid по умолчанию не переставляет элементы, чтобы заполнить пропуски. Добавьте контейнеру
grid-auto-flow: dense— браузер начнёт затыкать дыры мелкими элементами. Учтите: визуальный порядок при этом может отличаться от порядка в HTML. - Именованная область не применилась. Имя в
grid-areaдолжно точно совпадать с именем вgrid-template-areas, без кавычек. Опечатка в имени зоны молча ничего не сломает — элемент просто ляжет в первую свободную ячейку.
Что делать дальше
Сетки из этой инструкции — фундамент. Следующие шаги, которые стоит освоить по очереди:
- функция
minmax()в связке сclamp()для плавных размеров без медиазапросов; - выравнивание внутри ячеек через
justify-itemsиalign-self— когда содержимое ячеек разной высоты; - вложенные сетки: grid внутри ячейки другого grid для карточек со сложной внутренней структурой.
Держите открытой панель разработчика с подсветкой линий — на реальном макете она экономит больше времени, чем любая теория. Раскладку под мобильные экраны через переопределение grid-template-areas в медиазапросах вынесем в отдельный разбор, здесь мы собирали базовые макеты.
Карточки для маркетплейсов: Таблица товаров и папка фотографий на входе — комплект слайдов и описаний на выходе, по требованиям Wildberries и Ozon.
Спросить за 5 ₽Источники: CSS Grid Layout — MDN Web Docs, Can I use — CSS Grid Layout
Частые вопросы
А если мне нужна поддержка Internet Explorer 11?
Чем Grid отличается от Flexbox и что выбрать?
Карточки разной высоты выравниваются по самой высокой — это нормально?
Нужно ли писать вендорные префиксы вроде -webkit- и -moz-?
Почему у меня появилась лишняя строка или колонка, которую я не задавал?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.