Учимся верстать в сетке: большой гайд по CSS Grid
Знакомимся с самой гибкой и современной разметкой CSS.


Иллюстрация: Оля Ежак для Skillbox Media
При просмотре разных сайтов в интернете можно заметить, как аккуратно располагаются на них элементы независимо от размера экрана: навигация, кнопки, блоки с текстом и другие вещи. За это отвечает язык разметки CSS (Cascading Style Sheets). Она бывает разных видов, но сегодня поговорим об одном из них, самом адаптивном — CSS-гридах.
Из этой статьи вы узнаете:
- Что такое CSS Grid
- Как его создать
- Какие свойства есть у грид-контейнера
- А какие — у грид-элементов
- Как задать отступы между элементами
- Как выровнять сразу все элементы в грид-контейнере
- Как выровнять отдельные элементы
- Что такое вложенные гриды
- Что нужно запомнить
Что такое CSS Grid
Grid (сетка) — это вид разметки, в котором элементы на сайте расположены в виде таблицы. Главная фишка этой таблицы в гибкости — можно объединять отдельные ячейки, менять размеры строк и столбцов, регулировать отступы между ними. А ещё гриды хорошо приспосабливаются к разным размерам экрана, что делает их адаптивными.
Структура грида напоминает обычный Excel-файл: есть горизонтальные и вертикальные линии, которые вместе образуют много разных ячеек. Только, в отличие от файла в Excel, внутри ячеек находятся не выгрузки по зарплате за март, а элементы сайта: текст, картинки, кнопки, блоки HTML-кода и так далее. А формально все эти части грид-разметки называются так:
- grid-контейнер — самый главный элемент во всей разметке, в нём хранится всё содержимое сетки;
- grid-ячейка — единица грид-сетки, сюда можно положить один или несколько блоков кода;
- grid-линия — горизонтальная или вертикальная линия, разделяющая столбцы и колонки;
- grid-строка (row) — ряд ячеек;
- grid-столбец (column) — колонка ячеек;
- grid-элемент — какой-либо элемент сайта;
- grid-область (area) — пространство из ячеек, в CSS можно объединить несколько ячеек в одну и работать с ними как с единым целым.
А вот как они располагаются на схеме:

В отличие от Flexbox — другого популярного вида CSS-разметки — Grid позволяет создавать двумерные таблицы. Это значит, что в них могут быть одновременно и ряды, и колонки. А во Flexbox всё строго: можно выстроить элементы или в столбик, или в линию — сочетать оба метода нельзя.
За дело: создаём наш первый Grid
Чтобы опробовать Grid в деле, нам понадобится два файла: HTML и CSS. Начнём со «скелета» — создадим HTML-файл вот с таким содержимым (для удобства это можно сделать в онлайн-редакторе):
<head>
<title>CSS Grid Layout</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- Это будет грид-контейнер с пятью элементами внутри -->
<div class="container">
<div class="A">A</div>
<div class="B">B</div>
<div class="C">C</div>
<div class="D">D</div>
<div class="E">E</div>
</div>
</body>
Здесь мы задали несколько простых объектов — обычные латинские буквы A, B, C, D и E — и расположили их на отдельных строчках.
Теперь настало время объявить саму сетку. Для этого в той же папке создадим файл style.css и поместим туда вот такой код:
/* Объявляем grid-контейнер */
.container { /* Задаём свойства элементов HTML-класса «контейнер» */
display: grid; /* Режим отображения меняем на «сетку» */
}
Пока что ничего не изменилось — чтобы нашу сетку было видно, добавим ей стили: контейнер обведём зелёным цветом, а все элементы внутри него — чёрной штрих-пунктирной линией.
/* Добавляем оформление grid-контейнеру: */
.container {
border: 2px solid rgb(80, 145, 27); /* Обводим зелёной линией */
border-radius: 5px; /* Скругляем углы на 5 пикселей */
}
/* Добавляем оформление элементам grid-контейнера: */
.container * {
border: 1px dashed; /* Обводим чёрным пунктиром */
border-radius: 10px; /* Скругляем углы на 10 пикселей */
background-color: rgba(82, 29, 179, 0.5); /* Фон красим фиолетовым */
text-align: center; /* Контент размещаем в центре по горизонтали */
}
/*
Для разделения действий мы несколько раз объявили один и тот же элемент
.container. На самом деле все эти блоки — единое целое, и относятся к одному классу — container.
*/
Должно получиться примерно так:

Уже лучше! Но пока наши элементы расположены по дефолту и какой-то гибкой вёрсткой тут и не пахнет. Чтобы научиться настраивать сетку под себя, разберёмся со свойствами гридов.
Свойства грид-контейнера
Свойства грид-контейнера задают параметры таблицы — количество строк и столбцов, их размеры, расположение в сетке и другие.
Колонки (grid-template-columns)
Чтобы создать колонки, нужно просто записать их размеры через пробел. Размеры можно указывать в разных единицах измерения: пикселях, процентах, сантиметрах и так далее. Причём можно смешивать несколько единиц в пределах одного свойства.
Допустим, нам нужно создать три колонки: первая занимает одну треть экрана, вторая — ровно 100px, а третья — всё оставшееся место. Самый очевидный вариант — записать через проценты:
.container {
display: grid;
grid-template-columns: 30% 100px 70%;
}
Но тогда общая ширина всех колонок превысит 100%, и третья колонка уедет за пределы контейнера:

Чтобы избегать таких ситуаций, гридам придумали новую единицу измерения — фракцию (fr). Она позволяет разделить свободное пространство экрана на несколько частей и не возиться с ручной подгонкой процентов.
А нам того и надо — первому столбцу отдаём одну часть свободного пространства (1fr), третьему — две (2fr), а тот, что посередине, пускай забирает свои 100px:
.container {
display: grid;
grid-template-columns: 1fr 100px 2fr;
}
И вот какая получается красота — всё аккуратно и в рамочке:

Ряды (grid-template-rows)
Едем дальше. Захотели мы, допустим, задать нашей табличке размеры строк:
.container {
display: grid;
grid-template-rows: 3fr 2fr 2fr 1fr;
}
Но вдруг видим, что размеры двух строчек повторяются — они занимают ровно 2fr. Чтобы не писать дважды одно и то же, поместим их в функцию repeat. Она принимает на вход два параметра — размер строки во фракциях и количество его повторений:
grid-template-rows: 3fr repeat(2, 2fr) 1fr;
И полная, и краткая запись уместны — их можно чередовать в зависимости от контекста. Например, в нашем случае без функции можно было бы обойтись — но если надо создать, допустим, 10 колонок, она помогла бы сделать код более лаконичным и читаемым.
Вот как работает функция repeat наглядно:

Обратите внимание: высоту последней строчки E мы нигде не указывали, поэтому она остаётся дефолтной.
Области (grid-template-areas)
Одна из особенностей грид-разметки — возможность создавать области и гибко регулировать их размеры.
Чтобы создать область, объявим для каждого элемента в CSS-файле свойство grid-area — его параметром будет любое имя, какое захотите. Можно просто добавить в любое место CSS-файла этот код:
.A { grid-area: f; }
.B { grid-area: i; }
.C { grid-area: b; }
.D { grid-area: o; }
.E { grid-area: n; }
Затем в грид-контейнере создаём «матрицу» из этих имён:
.container {
display: grid;
grid-template-areas: "f f f f f i i i"
"f f f f f i i i"
"f f f f f i i i"
"f f f f f o b b"
"f f f f f n b b";
}
Вуаля! Наши элементы выстроились по шаблону:

Как это работает. Каждое имя в grid-template-areas соответствует определённому объекту. Одинаковые имена, стоящие рядом, собирают несколько ячеек в единое целое — то есть в грид-область:
- Элемент A с «псевдонимом» f занимает область в 25 ячеек.
- Элемент B (i) — в 9 ячеек.
- Элемент C (b) — в 4 ячейки.
- Элемент D (o) — в 1 ячейку.
- Элемент E (n) — тоже в 1 ячейку.
Сокращённое свойство (grid-template)
Свойство grid-template позволяет в краткой форме определить или столбцы со строками, или целые области.
1. Короткая форма для грид-строк и грид-колонок:
/* Сетка из строк и столбцов */
grid-template: grid-template-rows / grid-template-columns;
Фишка в том, что мы всего одной строчкой создаём целую таблицу — просто записываем через слеш количество рядов и столбцов. Для примера создадим сетку из трёх строк по 1fr и двух столбцов по 2fr.
.container{
display: grid;
grid-template: 1fr 1fr 1fr / 2fr 2fr;
}

Кстати, свойство grid-template тоже принимает функцию repeat.
.container{
display: grid;
grid-template: repeat(3, 1fr) / repeat(2, 2fr);
}
И, как видите, результат остаётся неизменным:

2. Короткая форма для грид-областей.
Также сокращённая запись поддерживает объявление грид-областей, нужно только объявить свойство grid-area для каждого объекта:
.container {
display: grid;
grid-template: "f f f i i"
"f f f i i"
"f f f b o"
". . n n n";
}
.A { grid-area: f; }
.B { grid-area: i; }
.C { grid-area: b; }
.D { grid-area: o; }
.E { grid-area: n; }
Профит:

Свойства грид-элементов
С помощью этих свойств можно прямо указать браузеру, где должны находиться элементы. Для этого нужно указать две точки: с какой линии элемент начинается и какой заканчивается — это работает как по горизонтали, так и по вертикали.

Вот так можно двигать элемент по горизонтали:
grid-column-start: 1;
Задаёт начальную позицию (линию) столбцов
grid-column-end: 3;
Задаёт конечную позицию (линию) столбцов
grid-column: grid-column-start / grid-column-end;
Объединённое свойство грид-линий столбцов: начало и конец
А вот так — по вертикали:
grid-row-start: 1;
Задаёт начальную позицию (линию) строк
grid-row-end: 4;
Задаёт конечную позицию (линию) строк
grid-row: grid-row-start / grid-row-end;
Объединённое свойство грид-линий строк: начало и конец
Но есть и одно общее свойство, объединяющее все четыре основных:
grid-area: grid-row-start / grid-column-start / grid-row-end / grid-column-end;
Теперь давайте попробуем задать эти свойства первым трём элементам из нашей конструкции с буквами:
/* Объявляем грид 5 × 3 */
.container {
display: grid;
grid-template: repeat(3, 1fr) / repeat(5, 1fr) ;
}
/* Расставляем первые три элемента: A, B и C */
.A {
grid-area: 1 / 1 / 4 / 4;
}
.B {
grid-column-start: 4;
grid-column-end: 6;
grid-row-start: 1;
grid-row-end: 3;
}
.C {
grid-column: 4 / 5;
grid-row: 3 / 4;
}
Этот код указывает нашим буквам, какие позиции занять в сетке:
- Элемент А занял область от первой до четвёртой линии — и по горизонтали, и по вертикали.
- Элемент B занял область от четвёртой до шестой линии по горизонтали и от первой до третьей по вертикали.
- Элемент С занял область от четвёртой до пятой линии по горизонтали и от третьей до четвёртой линии по вертикали.
- Ну а остальные расположились по дефолту :)
Выглядит так:

Grid-gap (отступы)
Используя grid-gap, можно регулировать интервалы между элементами в контейнере. Делается это с помощью двух параметров:
- column-gap — расстояние между колонками;
- row-gap — расстояние между строками.
Вот как это выглядит в коде:
.container {
column-gap: 1%;
row-gap: 1%;
}
Как и у grid-template, у gap есть сокращённая запись, где параметры column-gap и row-gap можно записать через пробел:
gap: 1% 1%;

Выравнивание грид-контейнера
Со свойствами элементов разобрались, теперь поговорим о том, как их выровнять в рамках контейнера или области.
justify-items
Что делает: выравнивает элементы в пределах области по горизонтали.
justify-items: stretch;

Растягивает элементы на всю ширину грид-ячейки
justify-items: start;

Располагает элементы в левой части грид-ячейки или области
justify-items: center;

Располагает элементы в центре грид-ячейки или области
justify-items: end;

Располагает элементы в правой части грид-ячейки или области
align-items
Что делает: выравнивает элементы в пределах области по вертикали.
align-items: stretch;

Растягивает элементы на всю длину грид-ячейки
align-items: start;

Располагает элементы в верхней части грид-ячейки
align-items: center;

Располагает элементы в центре грид-ячейки
align-items: end;

Располагает элементы в нижней части грид-ячейки
justify-content
Что делает: выравнивает элементы в пределах всего контейнера по горизонтали.
justify-content: start;

Располагает элементы в левой части грид-контейнера
justify-content: center;

Располагает элементы по центру грид-контейнера
justify-content: end;

Располагает все элементы в правой части грид-контейнера
justify-content: space-between;

Распределяет элементы по левому и правому краю. Первый элемент располагается ближе к началу, а последний — ближе к концу
justify-content: space-around;

Распределение с равным пространством между элементами и половиной этого пространства от краёв
justify-content: space-evenly;

Распределение с равным пространством и между элементами, и от краёв
align-content
Что делает: выравнивает элементы в пределах всего контейнера по вертикали.
Для начала увеличим высоту контейнера с помощью параметра height:
.container {
display: grid;
/* code... */
height: 200px;
}

Пока элементы просто растянулись по длине контейнера, а теперь попробуем применить к нему следующие свойства:
align-content: start;

Все элементы расположились в верхней части контейнера
align-content: center;

Все элементы расположились в середине грид-контейнера
align-content: space-between;

Элементы расположились по верхнему и нижнему краю. Первый элемент ближе к началу, последний — ближе к концу
align-content: space-around;

Распределение с равным пространством между элементами и половиной этого пространства от краёв
Выравнивание грид-элементов
Следующие свойства работают с отдельными грид-элементами, поэтому параметры мы будем прописывать не всему контейнеру, а элементу — скажем, с буквой A.
justify-self
Что делает: выравнивает грид-элементы по горизонтали.
justify-self: stretch;

Элемент A растянулся по всей длине грид-области
justify-self: center;

Элемент A расположился в центре грид-области
justify-self: start;

Элемент A расположился в начале грид-области
justify-self: end;

Элемент A расположился в конце грид-области
align-self
Что делает: выравнивает грид-элементы по вертикали.
align-self: stretch;

Элемент A растянулся по всей ширине грид-области
align-self: center;

Элемент A расположился в середине грид-области
align-self: start;

Элемент A расположился в начале грид-области
align-self: end;

Элемент A расположился в конце грид-области
Грид в гриде: вложенные гриды
В CSS грид бывает вложенным — это значит, что он содержит в себе другой грид-контейнер. Чтобы понять, как это работает, давайте немного пересоберём наш HTML-каркас, добавив в него ещё один подуровень элементов:
<head>
<title>CSS Grid Layout</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container">
<div class="A">A</div>
<div class="B">B</div>
<div class="С">C</div>
<!-- Тут начинается подуровень, содержащий 3 элемента -->
<div class="D">
<div class="E">E</div>
<div class="F">F</div>
<div class="G">G</div>
</div>
<div class="H">H</div>
<div class="J">J</div>
</div>
</body>
Для основного контейнера в CSS-файле создадим сетку 3 на 3:
/* Объявляем грид 3 × 3 */
.container {
display: grid;
grid-template-columns: repeat(3, 3fr);
grid-template-rows: repeat(3, 3fr);
}
И вот какая матрёшка у нас получилась:

А теперь для элемента D определим display: grid — то есть объявим внутри него ещё одну сетку. Для свойств строк и столбцов напишем параметр subgrid, который заимствует параметры родительского грида:
.D {
display: grid;
grid-template-columns: subgrid;
grid-template-rows: subgrid;
}

Готово! Теперь можно мастерски жонглировать элементами E, F, G, задавая им разное расположение в пределах элемента D (который тоже стал сеткой). Например, сделаем так, чтобы E начинался от второй вертикальной линии грида до третьей:
.E {
grid-column: 2 / 3;
}
Внутренние элементы, в свою очередь, расположились уже во вложенном гриде:

Что нужно запомнить
Сегодня мы узнали, что такое грид в CSS: как он работает, из чего состоит и как настраивается. Повторим ключевые моменты:
- Grid Layout в CSS — это гибкая разметка, при которой элементы располагаются в виде таблицы. Таблица состоит из ячеек, которые можно собирать в целые области.
- Чтобы создать грид, нужно в файле с CSS-разметкой добавить строчку display: grid.
- Грид состоит из родительского контейнера и вложенных в него элементов. Элементы могут занимать несколько ячеек, которые складываются в столбцы, колонки или области.
- Фракция — единица измерения в CSS, созданная для удобства — чтобы можно было задавать соотношения между элементами и не подгонять вручную проценты.
- Грид может содержать в себе другой грид — такая конструкция называется вложенным subgrid.
- Основными свойствами грид-контейнера являются: grid-template, grid-template-columns, grid-template-rows, grid-template-areas. Они позволяют задавать размеры колонок, строк или целых областей.
- За отступы между колонками грида отвечает свойство column-gap, а между рядами — row-gap.
- Горизонтально выровнять элементы контейнера можно с помощью justify-items и justify-content, а вертикально — с align-items и align-content.
- Настроить расположение элементов от определённой линии грид-сетки можно с помощью свойств:
- по горизонтальной оси: grid-column-start, grid-column-end, grid-column;
- по вертикальной оси: grid-row-start, grid-row-end, grid-row;
- или общим свойством grid-area.
- Выровнять конкретный элемент грида можно с помощью justify-self (по горизонтали) и align-self (по вертикали).
Больше интересного про код в нашем телеграм-канале. Подписывайтесь!