Учимся верстать в сетке: большой гайд по CSS Grid
2026-02-21 09:08 Diff

#статьи

  • 13 мар 2023
  • 0

Знакомимся с самой гибкой и современной разметкой CSS.

Иллюстрация: Оля Ежак для Skillbox Media

Программист, музыкант. Знает Java, C# и Unity3D, но не собирается останавливаться на достигнутом.

При просмотре разных сайтов в интернете можно заметить, как аккуратно располагаются на них элементы независимо от размера экрана: навигация, кнопки, блоки с текстом и другие вещи. За это отвечает язык разметки CSS (Cascading Style Sheets). Она бывает разных видов, но сегодня поговорим об одном из них, самом адаптивном — CSS-гридах.

Из этой статьи вы узнаете:

Grid (сетка) — это вид разметки, в котором элементы на сайте расположены в виде таблицы. Главная фишка этой таблицы в гибкости — можно объединять отдельные ячейки, менять размеры строк и столбцов, регулировать отступы между ними. А ещё гриды хорошо приспосабливаются к разным размерам экрана, что делает их адаптивными.

Структура грида напоминает обычный Excel-файл: есть горизонтальные и вертикальные линии, которые вместе образуют много разных ячеек. Только, в отличие от файла в Excel, внутри ячеек находятся не выгрузки по зарплате за март, а элементы сайта: текст, картинки, кнопки, блоки HTML-кода и так далее. А формально все эти части грид-разметки называются так:

  • grid-контейнер — самый главный элемент во всей разметке, в нём хранится всё содержимое сетки;
  • grid-ячейка — единица грид-сетки, сюда можно положить один или несколько блоков кода;
  • grid-линия — горизонтальная или вертикальная линия, разделяющая столбцы и колонки;
  • grid-строка (row) — ряд ячеек;
  • grid-столбец (column) — колонка ячеек;
  • grid-элемент — какой-либо элемент сайта;
  • grid-область (area) — пространство из ячеек, в CSS можно объединить несколько ячеек в одну и работать с ними как с единым целым.

А вот как они располагаются на схеме:

Изображение: Skillbox Media

В отличие от Flexbox — другого популярного вида CSS-разметки — Grid позволяет создавать двумерные таблицы. Это значит, что в них могут быть одновременно и ряды, и колонки. А во Flexbox всё строго: можно выстроить элементы или в столбик, или в линию — сочетать оба метода нельзя.

Чтобы опробовать 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. */

Должно получиться примерно так:

Изображение: Skillbox Media

Уже лучше! Но пока наши элементы расположены по дефолту и какой-то гибкой вёрсткой тут и не пахнет. Чтобы научиться настраивать сетку под себя, разберёмся со свойствами гридов.

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

Чтобы создать колонки, нужно просто записать их размеры через пробел. Размеры можно указывать в разных единицах измерения: пикселях, процентах, сантиметрах и так далее. Причём можно смешивать несколько единиц в пределах одного свойства.

Допустим, нам нужно создать три колонки: первая занимает одну треть экрана, вторая — ровно 100px, а третья — всё оставшееся место. Самый очевидный вариант — записать через проценты:

.container { display: grid; grid-template-columns: 30% 100px 70%; }

Но тогда общая ширина всех колонок превысит 100%, и третья колонка уедет за пределы контейнера:

Изображение: Skillbox Media

Чтобы избегать таких ситуаций, гридам придумали новую единицу измерения — фракцию (fr). Она позволяет разделить свободное пространство экрана на несколько частей и не возиться с ручной подгонкой процентов.

А нам того и надо — первому столбцу отдаём одну часть свободного пространства (1fr), третьему — две (2fr), а тот, что посередине, пускай забирает свои 100px:

.container { display: grid; grid-template-columns: 1fr 100px 2fr; }

И вот какая получается красота — всё аккуратно и в рамочке:

Изображение: Skillbox Media

Едем дальше. Захотели мы, допустим, задать нашей табличке размеры строк:

.container { display: grid; grid-template-rows: 3fr 2fr 2fr 1fr; }

Но вдруг видим, что размеры двух строчек повторяются — они занимают ровно 2fr. Чтобы не писать дважды одно и то же, поместим их в функцию repeat. Она принимает на вход два параметра — размер строки во фракциях и количество его повторений:

grid-template-rows: 3fr repeat(2, 2fr) 1fr;

И полная, и краткая запись уместны — их можно чередовать в зависимости от контекста. Например, в нашем случае без функции можно было бы обойтись — но если надо создать, допустим, 10 колонок, она помогла бы сделать код более лаконичным и читаемым.

Вот как работает функция repeat наглядно:

Изображение: Skillbox Media

Обратите внимание: высоту последней строчки E мы нигде не указывали, поэтому она остаётся дефолтной.

Одна из особенностей грид-разметки — возможность создавать области и гибко регулировать их размеры.

Чтобы создать область, объявим для каждого элемента в 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"; }

Вуаля! Наши элементы выстроились по шаблону:

Изображение: Skillbox Media

Как это работает. Каждое имя в grid-template-areas соответствует определённому объекту. Одинаковые имена, стоящие рядом, собирают несколько ячеек в единое целое — то есть в грид-область:

  • Элемент A с «псевдонимом» f занимает область в 25 ячеек.
  • Элемент (i) — в 9 ячеек.
  • Элемент (b) — в 4 ячейки.
  • Элемент (o) — в 1 ячейку.
  • Элемент E (n) — тоже в 1 ячейку.

Свойство grid-template позволяет в краткой форме определить или столбцы со строками, или целые области.

1. Короткая форма для грид-строк и грид-колонок:

/* Сетка из строк и столбцов */ grid-template: grid-template-rows / grid-template-columns;

Фишка в том, что мы всего одной строчкой создаём целую таблицу — просто записываем через слеш количество рядов и столбцов. Для примера создадим сетку из трёх строк по 1fr и двух столбцов по 2fr.

.container{ display: grid; grid-template: 1fr 1fr 1fr / 2fr 2fr; }Изображение: Skillbox Media

Кстати, свойство grid-template тоже принимает функцию repeat.

.container{ display: grid; grid-template: repeat(3, 1fr) / repeat(2, 2fr); }

И, как видите, результат остаётся неизменным:

Изображение: Skillbox Media

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; }

Профит:

Изображение: Skillbox Media

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

Изображение: Skillbox Media

Вот так можно двигать элемент по горизонтали:

Задаёт начальную позицию (линию) столбцов

Задаёт конечную позицию (линию) столбцов

grid-column: grid-column-start / grid-column-end;

Объединённое свойство грид-линий столбцов: начало и конец

А вот так — по вертикали:

Задаёт начальную позицию (линию) строк

Задаёт конечную позицию (линию) строк

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 занял область от четвёртой до шестой линии по горизонтали и от первой до третьей по вертикали.
  • Элемент С занял область от четвёртой до пятой линии по горизонтали и от третьей до четвёртой линии по вертикали.
  • Ну а остальные расположились по дефолту :)

Выглядит так:

Изображение: Skillbox Media

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

  • column-gap — расстояние между колонками;
  • row-gap — расстояние между строками.

Вот как это выглядит в коде:

.container { column-gap: 1%; row-gap: 1%; }

Как и у grid-template, у gap есть сокращённая запись, где параметры column-gap и row-gap можно записать через пробел:

gap: 1% 1%; Изображение: Skillbox Media

Со свойствами элементов разобрались, теперь поговорим о том, как их выровнять в рамках контейнера или области.

Что делает: выравнивает элементы в пределах области по горизонтали.

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

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

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

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

Что делает: выравнивает элементы в пределах области по вертикали.

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

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

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

Располагает элементы в нижней части грид-ячейки

Что делает: выравнивает элементы в пределах всего контейнера по горизонтали.

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

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

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

justify-content: space-between;

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

justify-content: space-around;

Распределение с равным пространством между элементами и половиной этого пространства от краёв

justify-content: space-evenly;

Распределение с равным пространством и между элементами, и от краёв

Что делает: выравнивает элементы в пределах всего контейнера по вертикали.

Для начала увеличим высоту контейнера с помощью параметра height:

.container { display: grid; /* code... */ height: 200px; }Изображение: Skillbox Media

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

Все элементы расположились в верхней части контейнера

Все элементы расположились в середине грид-контейнера

align-content: space-between;

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

align-content: space-around;

Распределение с равным пространством между элементами и половиной этого пространства от краёв

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

Что делает: выравнивает грид-элементы по горизонтали.

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

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

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

Элемент A расположился в конце грид-области

Что делает: выравнивает грид-элементы по вертикали.

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

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

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

Элемент 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); }

И вот какая матрёшка у нас получилась:

Изображение: Skillbox Media

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

.D { display: grid; grid-template-columns: subgrid; grid-template-rows: subgrid; }Изображение: Skillbox Media

Готово! Теперь можно мастерски жонглировать элементами E, F, G, задавая им разное расположение в пределах элемента D (который тоже стал сеткой). Например, сделаем так, чтобы E начинался от второй вертикальной линии грида до третьей:

.E { grid-column: 2 / 3; }

Внутренние элементы, в свою очередь, расположились уже во вложенном гриде:

Изображение: Skillbox Media

Сегодня мы узнали, что такое грид в 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 (по вертикали).
Курс с трудоустройством: «Профессия Фронтенд-разработчик + ИИ» Узнать о курсе