Инструмент Grid появился в CSS в 2017 году. Он позволяет управлять расположением элементов на странице в двух измерениях — по горизонтали и вертикали, делая вёрстку гибкой. На момент написания статьи CSS Grid поддерживается примерно в 97,8% браузеров.
Сегодня подробно разберёмся, как это всё работает, как использовать в реальных макетах и какой ещё есть способ отцентрировать div. На собеседовании это обязательно спросят.
Что такое CSS Grid
CSS Grid позволяет создавать сложные макеты, адаптирующиеся к размерам экрана. Его особенность в том, что сетка строк и колонок полностью задаётся в CSS и нам не нужно добавлять дополнительные HTML-элементы.
Вот так можно создать сетку, которая делит один HTML-элемент (div) на строки и колонки — только с помощью CSS:
<div class="grid">Грид</div>
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(2, 150px);
gap: 10px;
}
DOM-узел один, но элементов внутри него — 6:
Можно задавать количество строк и колонок, их размеры и расположение элементов в сетке. Сами элементы можно комбинировать, растягивать и сжимать, чтобы они занимали нужное пространство. И всё это позволяют добиться адаптивных макетов, которые корректно отображаются на разных экранах.
Дальше посмотрим, как именно это делается и из чего состоит сетка.
Основные понятия и терминология
Грид-контейнер
Для начала нужно превратить элемент в грид-контейнер с помощью свойства display: grid
или inline-grid
. Грид-контейнер — это родительский контейнер, который создаёт сетку и делает дочерние элементы её ячейками.
По умолчанию, когда мы прописываем свойство grid
, создаётся сетка с одной колонкой, а строки добавляются автоматически в зависимости от количества элементов внутри контейнера. Это называется неявной сеткой, потому что мы заранее не задаём структуру:
<div class="grid">
<div>Раз</div>
<div>Два</div>
<div>Три</div>
</div>
.grid {
/* Создаём грид-контейнер */
display: grid;
/* Добавляем промежуток между элементами сетки */
gap: 10px;
}
div {
/* Для наглядности добавим обводку */
outline: 1px solid #683eef;
}
В этом макете:
- Строки появляются автоматически и каждому элементу создаётся своя строка.
- Высота контейнера зависит от контента. Грид-контейнер расширяется или сжимается, подстраиваясь под содержимое.
Такой эффект возникает из-за базового поведения Flow Layout (потока документа) — стандартного алгоритма CSS, где блоки автоматически растягиваются по вертикали, чтобы вместить весь контент.
Дальше разберём основные составляющие грид-контейнера:
Грид-треки (грид-полосы)
Грид-трек — это промежуток между двумя соседними линиями сетки. Он может быть:
- Горизонтальным треком — строка (row), промежуток между двумя горизонтальными линиями.
- Вертикальным треком — колонка (column), промежуток между двумя вертикальными линиями.
Треки определяют пространство, где размещаются ячейки. На примере ниже — горизонтальный трек-строка:
Треки помогает описать, как элементы размещаются в сетке и как контролировать их расположение.
Грид-ячейки
Грид-ячейка (grid cell) — это наименьший элемент сетки, образованный пересечением одной строки и одной колонки. Проще говоря, это пространство между двумя соседними грид-линиями. Ячейки формируются автоматически при задании колонок и строк.
Это базовая единица, в которой может размещаться контент. Каждая ячейка может содержать один или несколько элементов — текст, изображение и так далее — или быть пустой. Ячейки формируются автоматически при задании колонок и строк.
Грид-области
Грид-область (grid area) — это прямоугольная область, состоящая из нескольких смежных грид-ячеек. Она создаётся за счёт объединения строк и колонок и позволяет группировать элементы для управления их расположением в сетке.
Грид-линии
Грид-линии (grid lines) — это границы, которые разделяют строки и колонки в CSS Grid. Они определяют, где начинаются и заканчиваются ячейки, треки и области.
У каждой линии есть свой порядковый номер: их используют в коде, когда в сложном макете нужно выделить определённое место в сетке под какой-то элемент. Об этом поговорим позже.
Промежутки (gap)
gap
задаёт расстояние (промежуток) между строками и колонками в сетке. Это удобно для создания равномерных отступов между элементами без использования margin
или padding
на самих элементах.
Свойство gap
— это сокращённая запись для двух отдельных свойств:
row-gap
— промежуток между строками;column-gap
— промежуток между колонками.
.container {
display: grid;
/* 10px между строками, 30px между колонками */
gap: 10px 30px;
}
Свойства грид-контейнера
Теперь разберём подробно, как именно создавать сетки.
display: grid и display: inline-grid
Сетка может быть блочной или строчной, в зависимости от того, какое свойство мы применяем к грид-контейнеру. Разница в том, что:
display: grid
делает контейнер блочным элементом, который занимает всю доступную ширину;display: inline-grid
делает контейнер строчным (инлайновым) элементом, который подстраивается под содержимое и занимает только необходимую ширину.
В зависимости от того, какой нужен макет, мы выбираем соответствующее свойство: блочная сетка подойдёт для создания крупных макетов — галерей изображений, карточек товаров, а строчная — для небольших компонентов, например мини-календарей, виджетов или наборов кнопок.
grid-template-columns
По умолчанию CSS Grid создаёт сетку из одной колонки. Чтобы задать количество и ширину колонок, используется свойство grid-template-columns
.
Например, так можно создать простейшую сетку с двумя колонками:
/* Определяем родительский контейнер как CSS Grid */
.parent {
display: grid; /* Включаем CSS Grid для этого контейнера */
/* Создаём две колонки: первая занимает 25% ширины, вторая — 75% */
grid-template-columns: 25% 75%;
/* Добавляем промежуток в 10px между колонками и строками */
gap: 10px;
/* Добавляем рамку вокруг всего грид-контейнера для наглядности */
border: 1px solid black;
}
/* Стили для дочерних элементов внутри грид-контейнера */
.child {
/* Цвет фона для наглядности */
background: lightblue;
/* Центрируем текст по горизонтали */
text-align: center;
/* Добавляем внутренний отступ, чтобы контент не прилипал к краям */
padding: 10px;
/* Добавляем рамку вокруг каждого элемента сетки */
border: 1px solid black;
}
В этом примере сетка делится на 2 колонки: первая занимает 25% ширины контейнера, вторая — 75%.
Вместо фиксированных процентов или пикселей можно использовать fr
— единицу, означающую долю свободного пространства:
.parent {
display: grid;
grid-template-columns: 1fr 3fr;
}
Как это работает:
- 1fr + 3fr = всего 4 единицы пространства.
- Первая колонка займёт ¼ ширины контейнера.
- Вторая колонка — оставшиеся ¾.
Единица fr
позволяет делать макет более адаптивным. Проценты — фиксированные, поэтому колонки не подстраиваются под содержимое. А доли — гибкие, и колонки могут расширяться и сжиматься, адаптируясь к содержимому.
Например, если в колонке находится изображение, то ширина в процентах может сделать её слишком узкой, и контент выйдет за границы. Доля же автоматически распределит пространство, учитывая размеры контента.
grid-template-rows
Аналогично мы можем задать количество и ширину строк через свойство grid-template-rows. Поменяем в примере выше раскладку:
grid-template-rows
Аналогично мы можем задать количество и ширину строк через свойство grid-template-rows
. Поменяем в примере выше раскладку:
.parent {
display: grid;
/* Первая строка занимает 1 часть пространства, вторая — 2 части */
grid-template-rows: 1fr 2fr;
gap: 10px;
border: 1px solid black;
}
Можно комбинировать эти свойства и создавать более сложные макеты. Например:
.parent {
display: grid;
/* Создаём три колонки одинаковой ширины */
grid-template-columns: 1fr 1fr 1fr;
/* Задаём две строки фиксированной высоты по 100px */
grid-template-rows: 100px 100px;
gap: 10px;
border: 1px solid black;
}
Такой шаблон удобно использовать, когда сетка небольшая и проще прописать размеры явно.
grid-auto-columns и grid-auto-rows
Если количество элементов внутри грид-контейнера превышает заданные колонки и строки, то CSS автоматически создаёт дополнительные ряды и колонки. Через свойства grid-auto-columns
и grid-auto-rows
мы можем управлять размерами этих автоматически создаваемых ячеек.
Например:
.parent {
display: grid;
grid-template-rows: 100px;
grid-template-columns: 1fr 1fr;
grid-auto-rows: 50px;
}
В этом макете:
- Один явно заданный ряд высотой 100px —
grid-template-rows: 100px;
- Две колонки, каждая занимает равную часть пространства (1fr) —
grid-template-columns: 1fr 1fr;
- Если количество элементов превышает одну строку, создаются дополнительные ряды. Их высота определяется через свойство
grid-auto-rows
и составляет 50px —grid-auto-rows: 50px;
Аналогично мы можем указать размеры автоматически создаваемых колонок с помощью свойства grid-auto-columns
:
.parent {
display: grid;
/* Задаём первую колонку фиксированной ширины 100px */
grid-template-columns: 100px;
/* Задаём две строки фиксированной высоты по 100px каждая */
grid-template-rows: 100px 100px;
/* Если элементов больше, чем одна колонка, создаются дополнительные колонки шириной 50px */
grid-auto-columns: 50px;
}
Свойства можно комбинировать, чтобы управлять как строками, так и колонками:
.parent {
display: grid;
/* Фиксированные колонки: четыре колонки шириной 100px каждая */
grid-template-columns: 100px 100px 100px 100px;
/* Первая строка фиксированной высоты */
grid-template-rows: 100px;
/* Если элементов больше, автоматически создаются строки высотой 50px */
grid-auto-rows: 50px;
/* Если элементов больше, чем 4 колонки, создаются новые колонки шириной 75px */
grid-auto-columns: 75px;
/* Промежутки между ячейками */
gap: 10px;
}
При этом по умолчанию новые элементы добавляются в строки (row
). Чтобы элементы создавали новые колонки, нужно явно это прописать в свойстве grid-auto-flow
:
grid-auto-flow: column
После этого новые элементы будут добавляться согласно свойству grid-auto-columns: 75px
:
Функция repeat()
Чтобы вручную прописывать число колонок, мы можем воспользоваться функцией repeat
. Допустим, нужно сверстать календарь с семью равными ячейками в ряду. Чтобы не писать семь раз 1fr
, можно сделать так:
.calendar {
display: grid;
grid-template-columns: repeat(7, 1fr);
}
Так мы говорим, что нужно создать сетку из 7 колонок, каждая из которых занимает равную долю пространства. Функция repeat
позволяет сократить запись и сделать код более читаемым, особенно если нужно создать большое количество одинаковых колонок или строк:
Функция minmax()
Функция minmax()
позволяет задать диапазон значений для размеров колонок или строк. Это полезно, когда нужно, чтобы элемент сохранял минимальный размер, но при этом мог увеличиваться при наличии свободного пространства.
Например:
.container {
display: grid;
/* Создаём 3 колонки: минимальная ширина 150px, максимальная — равные доли свободного пространства */
grid-template-columns: repeat(3, minmax(150px, 1fr));
gap: 10px;
}
Получается вот так:
Колонки сохраняют минимальную ширину, но при увеличении размеров экрана растягиваются.
auto-fill и auto-fit
Свойства auto-fill
и auto-fit
позволяют автоматически создавать колонки или строки, но работают по-разному:
auto-fill
создаёт колонки по размеру контейнера, даже если в них нет контента. Если позволяет ширина, пустые колонки остаются видимыми.auto-fit
подгоняет количество колонок под контент. Если позволяет ширина, элементы будут растягиваться, а лишние колонки схлопнутся.
В коде это будет выглядеть так:
/* Грид с auto-fill */
.auto-fill {
display: grid;
/* Создаёт столько колонок, сколько поместится, минимальный размер 150px,
оставшееся пространство делится поровну */
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
}
/* Грид с auto-fit */
.auto-fit {
display: grid;
/* Аналогично auto-fill, но пустые ячейки схлопываются, если контента меньше */
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}
grid-template-areas
Шаблоны грид-областей — одна из самых крутых штук, которые есть в CSS. Суть в том, что она позволяет прямо в коде визуально описать, как должен выглядеть макет. Допустим, мы хотим создать классический макет с шапкой, основным контентом и боковой панелью:
.parent {
display: grid;
/* Две колонки: первая уже, вторая шире */
grid-template-columns: 2fr 5fr;
/* Первая строка фиксирована, вторая занимает оставшееся пространство */
grid-template-rows: 50px 1fr;
/* Описание областей сетки */
grid-template-areas:
"sidebar header"
"sidebar main";
gap: 10px;
border: 2px solid black;
height: 300px;
}
/* Стили для ячеек */
.sidebar {
/* Привязка элемента к области "sidebar" */
grid-area: sidebar;
background: lightblue;
padding: 20px;
}
.header {
/* Привязка элемента к области "header" */
grid-area: header;
background: lightgreen;
padding: 20px;
}
.main {
/* Привязка элемента к области "main" */
grid-area: main;
background: lightcoral;
padding: 20px;
}
Самое интересное происходит здесь:
grid-template-areas:
"sidebar header"
"sidebar main";
Мы задаём структуру сетки прямо в CSS, описывая её текстовой схемой. Каждое имя области в кавычках представляет отдельную область сетки, а повторяющиеся названия объединяют ячейки. То есть визуально это можно представить так:
┌──────────┬──────────┐
│ sidebar │ header │
│ sidebar │ main │
└──────────┴──────────┘
В готовом макете это будет выглядеть так:
Свойства грид-элементов
Теперь посмотрим, как управлять элементами внутри сеток.
grid-column и grid-row
Свойства grid-column
и grid-row
управляют расположением элемента в сетке, указывая, на каких линиях начинается и заканчивается элемент. Это даёт возможность задавать, сколько колонок или строк должен занимать элемент. Можно создавать нестандартные макеты, выделять элементы, занимающие больше места, например баннеры или изображения.
Синтаксис свойства:
grid-column: start / end;
grid-row: start / end;
В свойстве мы приписываем два числовых параметра: start
— это грид-линия начала элемента в сетке, а end — грид-линия, на которой элемент заканчивается (не включительно).
Например, нужно, чтобы элемент занимал 2 колонки и 1 строку. Пишем так:
.item {
grid-column: 1 / 3;
grid-row: 1 / 2;
}
Это значит, что элемент по горизонтали растягивается с первой по третью грид-линию, а по вертикали — с первой по вторую:
Линии сетки начинаются с 1 и увеличиваются слева направо (для колонок) и сверху вниз (для строк). Если указать −1 в качестве значения, элемент растянется до последней линии сетки.
Что задать количество колонок или строк без указания конкретных линий, используется ключевое слово span
:
.item {
/* Элемент начинается с первой линии и растягивается на 3 колонки */
grid-column: 1 / span 3;
/* Элемент занимает только первую строку */
grid-row: 1 / 2;
}
Выглядеть это будет так:
grid-area
Свойство grid-area
позволяет одновременно задать начальные и конечные грид-линии для колонок и строк, а ещё использовать именованные области, созданные с помощью grid-template-areas
.
Синтаксис такой:
grid-area: row-start / column-start / row-end / column-end;
В параметрах свойства мы прописываем:
row-start
— начальная линия строки;column-start
— начальная линия колонки;row-end
— конечная линия строки;column-end
— конечная линия колонки.
Например, мы можем задать размеры определённых областей макета:
.header {
/* Первая строка, занимает все 4 колонки */
grid-area: 1 / 1 / 2 / 5;
background: lightblue;
}
.footer {
/* Нижняя строка, занимает 3 колонки */
grid-area: 4 / 2 / 5 / 5;
background: lightsalmon;
}
Такая запись позволяет сократить код, задавая позиции сразу для строк и колонок, и работает как с именованными областями, так и с номерами линий.
justify-self и align-self
Эти свойства управляют выравниванием отдельного элемента внутри своей ячейки.
justify-self
: выравнивание по горизонтали (start, center, end, stretch
)align-self
: выравнивание по вертикали (start, center, end, stretch
)
justify-self:
align-self:
Выравнивание и размещение элементов
justify-items и align-items
Свойства justify-items
и align-items
применяются, когда нужно задать одинаковое выравнивание для всех элементов внутри грид-контейнера. В отличие от justify-self
и align-self
, которые управляют выравниванием отдельного элемента, justify-items
и align-items
задают выравнивание сразу для всех ячеек сетки.
justify-items
и align-items
задаются в родительском контейнере:
.parent {
display: grid;
/* Создаём сетку из 3 колонок по 100px каждая */
grid-template-columns: repeat(3, 100px);
/* Создаём сетку из 1 строки 100px*/
grid-template-rows: repeat(1, 100px);
/* Добавляем промежуток между ячейками 10px */
gap: 10px;
/* Центрируем содержимое всех ячеек по горизонтали */
justify-items: center;
/* Центрируем содержимое всех ячеек по вертикали */
align-items: center;
}
justify-content и align-content
justify-content
и align-content
— это свойства, которые задаются в родительском грид-контейнере. Они управляют расположением всей сетки целиком внутри родительского элемента, если у контейнера остаётся свободное пространство.
justify-content
выравнивает сетку по горизонтали.align-content
выравнивает сетку по вертикали.
Свойства работают только тогда, когда сетка меньше доступного пространства. Если сетка заполняет весь контейнер, эти свойства не будут заметны.
Могут принимать одно из значений:
start
— прижимает сетку к началу оси.center
— центрирует сетку.end
— прижимает сетку к концу оси.space-between
— равномерно распределяет ячейки, первая и последняя прижаты к краям.space-around
— равномерно распределяет с равными отступами вокруг элементов.space-evenly
— равномерное распределение, одинаковые промежутки между элементами и краями.
👉 Для того чтобы применить к контейнеру одновременно оба свойства и отцентрировать его по вертикали и горизонтали, можно использовать синтаксический сахар place-content
:
.parent {
display: grid;
place-content: center;
}
Управление порядком отображения
С помощью свойства order
можно изменить порядок элементов в сетке, независимо от того, как они расположены в HTML.
По умолчанию у всех элементов order: 0
. Если задать разным элементам разные значения, они будут отображаться в порядке от меньшего к большему. Это полезно, когда нужно поменять расположение элементов на странице, сохраняя структуру кода в HTML.
На этом примере порядок элементов задаётся не в HTML, а в CSS:
По умолчанию у всех элементов order: 0
. Элемент со значением −1 отобразится первым, потом 0 и так далее в порядке увеличения.
👉 Здесь важно не забывать о доступности: если переставить элементы с помощью grid-area
или order
, это может создать путаницу для пользователей, которые используют экранные дикторы. Они будут воспринимать информацию в логическом порядке HTML, в то время как визуально элементы будут расположены иначе.
Поэтому лучше придерживаться логичного порядка элементов в HTML. Grid — это инструмент для визуального оформления, а не для изменения структуры документа. Если всё же нужно переставить элементы на экране, но оставить их последовательность в коде, лучше протестировать результат с помощью инструментов доступности.
Грид в гриде: вложенные гриды
Иногда для создания сложных макетов одной сетки недостаточно. Тогда в один грид вкладывают другие.
Вложенные гриды — это когда один из элементов сетки (грид-элемент) становится грид-контейнером для своих дочерних элементов. Так создаётся независимая сетка внутри ячейки основной сетки.
Например, на странице есть заголовок, боковое меню и основной контент. Внутри блока с контентом нужно расположить карточки товаров. Для этого можно сделать основной грид-контейнер, а затем создать ещё один внутри блока с карточками:
Вложенные гриды полезны, когда нужно создать сложный макет, где внутри одного элемента требуется дополнительная структура.
Советы
CSS Grid отлично подходит для создания сложных макетов, где элементы нужно размещать сразу в двух измерениях — по горизонтали и вертикали. Гриды упрощают работу с многоколоночными и многострочными сетками, делают код чище, а управление отступами через gap
интуитивным. Можно сделать адаптивный макет без медиазапросов только на одних гридах.
А вот если в макете нет сложной структуры и требуется расположить элементы последовательно в одну линию, то мудрить с гридами не стоит — лучше выбрать Flexbox.
Бывают ситуации, когда лучше сочетать обе технологии. Например, грид для общей структуры макета, а флексбокс — для выравнивания элементов внутри отдельных грид-областей.Для отладки макетов на гридах лучше использовать браузер Firefox. Он может отображать названия грид-областей прямо поверх сетки и даже показывает визуальное представление значения grid-template-areas
в углу экрана. Это помогает быстрее понять, как именно элементы распределяются в макете, и упростить процесс отладки.