Код
#статьи

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

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

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

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

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


Что такое CSS Grid

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

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

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

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

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

В отличие от 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.
*/

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

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

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

Свойства грид-контейнера

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

Колонки (grid-template-columns)

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

Допустим, нам нужно создать три колонки: первая занимает одну треть экрана, вторая — ровно 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

Ряды (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 наглядно:

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

Обратите внимание: высоту последней строчки 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";
}

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

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

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

  • Элемент A с «псевдонимом» f занимает область в 25 ячеек.
  • Элемент (i) — в 9 ячеек.
  • Элемент (b) — в 4 ячейки.
  • Элемент (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;                        
}
Изображение: 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-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 занял область от четвёртой до шестой линии по горизонтали и от первой до третьей по вертикали.
  • Элемент С занял область от четвёртой до пятой линии по горизонтали и от третьей до четвёртой линии по вертикали.
  • Ну а остальные расположились по дефолту :)

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

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

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%; 
Изображение: Skillbox Media

Выравнивание грид-контейнера

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

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;
}
Изображение: Skillbox Media

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

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

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

Изображение: 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 (по вертикали).

Больше интересного про код в нашем телеграм-канале. Подписывайтесь!

Проверьте свой английский. Бесплатно ➞
Нескучные задания: small talk, поиск выдуманных слов — и не только. Подробный фидбэк от преподавателя + персональный план по повышению уровня.
Пройти тест
Понравилась статья?
Да

Пользуясь нашим сайтом, вы соглашаетесь с тем, что мы используем cookies 🍪

Ссылка скопирована