CSS Grid Layout представляет двумерную сетку для CSS. Grid (здесь и далее подразумевается CSS Grid Layout ) можно использовать для размещения основных областей страницы или небольших элементов пользовательского интерфейса. В этой статье описывается компоновка сетки CSS и новая терминология, которая является частью спецификации CSS Grid Layout Level 1. Функции, показанные в этом обзоре, будут более подробно описаны в остальной части данного руководства.
Что такое Grid?
Grid представляет собой пересекающийся набор горизонтальных и вертикальных линий - один набор определяет столбцы, а другой строки. Элементы могут быть помещены в сетку, соответственно строкам и столбцам. Grid имеет следующие функции:
Фиксированные и гибкие размеры полос
Вы можете создать сетку с фиксированными размерами полос — например, используя пиксели. Вы также можете создать сетку с гибкими размерами, используя проценты или новую единицу измерения - fr, предназначенную для этой цели.
Расположение элемента
Вы можете размещать элементы в заданном месте Grid, используя номера строк, имена или путем привязки к области Grid. Grid также содержит алгоритм управления размещением элементов, не имеющих явной позиции в Grid.
Создание дополнительных полос для хранения контента
Вы можете определить явную сетку с макетом сетки, но спецификация также касается контента, добавленного за пределами объявленной сетки, при необходимости добавляя дополнительные строки и столбцы. Включены такие функции, как добавление «столько столбцов, сколько будет помещено в контейнер».
Управление выравниванием
Grid содержит функции выравнивания, чтобы мы могли контролировать, как элементы выравниваются после размещения в области сетки, и как выравнивается весь Grid.
Управление перекрывающимся контентом
В ячейку сетки может быть помещено более одного элемента, или области могут частично перекрывать друг друга. Затем это расслоение можно контролировать с помощью z-index
.
Grid - это мощная спецификация и в сочетании с другими частями CSS, такими как flexbox, может помочь вам создать макеты, которые ранее невозможно было построить в CSS. Все начинается с создания сетки в вашем grid контейнере.
Grid контейнер
Мы создаем grid контейнер, объявляя display: grid или display: inline-grid на элементе. Как только мы это сделаем, все прямые дети этого элемента станут элементами сетки.
В этом примере есть div, содержащий класс wrapper с пятью потомками
<div class="wrapper">
<div>One</div>
<div>Two</div>
<div>Three</div>
<div>Four</div>
<div>Five</div>
</div>
Сделаем wrapper grid контейнером
.wrapper {
display: grid;
}
Все прямые потомки теперь являются grid элементами. В веб-браузере вы не увидите никакой разницы в отображении элементов, поскольку Grid создал единую сетку столбцов для элементов. На данный момент вам может оказаться удобным работать в Firefox Developer Edition, в котором есть Grid Inspector, доступный как часть инструментов разработчика. Если вы просмотрите этот пример в Firefox и проверите Grid, вы увидите маленький значок рядом с display: grid. Нажмите этот значок, и сетка на этом элементе будет наложена в окне браузера.
По мере вашего обучения и последующей работы с CSS Grid Layout этот инструмент даст вам лучшее визуальное представление о том, что происходит с вашей сеткой.
Если мы хотим, чтобы это стало более похожим на сетку, нам нужно добавить полосы.
Grid Tracks
Мы определяем ряды и столбцы в нашей сетке при помощи свойств grid-template-columns
и grid-template-rows
. Это определяет полосы сетки. Полоса сетки — это место между любыми двумя линиями сетки. На изображении ниже вы можете увидеть подсветку полосы — первого трека ряда в нашей сетке.
Можно дополнить пример выше, добавив свойство grid-template-columns
и задав размеры полос колонок.
В примере ниже мы создаём сетку с шириной колонки 200px. Каждый дочерний элемент сетки будет располагаться в отдельной ячейке сетки.
<div class="wrapper">
<div>One</div>
<div>Two</div>
<div>Three</div>
<div>Four</div>
<div>Five</div>
</div>
.wrapper {
display: grid;
grid-template-columns: 200px 200px 200px;
}
Единица измерения fr
Размер треков (полос) может быть задан с помощью любой единицы длины. Спецификация также вводит дополнительную единицу длины, позволяющую создавать эластичные (flexible) грид-треки. Новая единица длины fr
представляет собой долю (fraction) доступного пространства в грид-контейнере. Определение грида в коде ниже создаст три трека равной длины, которые будут увеличиваться и уменьшаться в размерах в соответствии с доступным пространством.
<div class="wrapper">
<div>One</div>
<div>Two</div>
<div>Three</div>
<div>Four</div>
<div>Five</div>
</div>
.wrapper {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
В следующем примере мы создаем грид с треком в 2fr
и двумя треками по 1fr
. Доступное пространство разбивается на четыре части. Две части занимает первый трек, и две части - два оставшихся.
.wrapper {
display: grid;
grid-template-columns: 2fr 1fr 1fr;
}
В последнем примере смешаем треки с абсолютной длиной и треки с длиной во fr. Размер первого трека 500 пикселей, и эта фиксированная ширина убирается из доступного пространства. Оставшееся пространство разбивается на три части и пропорционально разделяется между двумя эластичными треками.
.wrapper {
display: grid;
grid-template-columns: 500px 1fr 2fr;
}
Задание треков с помощью нотации repeat()
В огромных гридах с большим количеством треков можно использовать нотацию repeat()
, чтобы повторить структуру треков или ее часть. Например, такое задание грида:
.wrapper {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
можно записать вот так:
.wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
Repeat-нотацию можно использовать как часть списка треков. В следующем примере создается грид с начальным треком шириной в 20 пикселей, шестью треками шириной в 1fr и последним треком шириной в 20 пикселей.
.wrapper {
display: grid;
grid-template-columns: 20px repeat(6, 1fr) 20px;
}
Repeat-нотация в качестве аргумента принимает список треков, поэтому с ее помощью можно создавать структуру из повторяющихся треков. В следующем примере грид состоит из 10 треков: за треком шириной 1fr
следует трек шириной 2fr
, и все это дело повторяется пять раз.
.wrapper {
display: grid;
grid-template-columns: repeat(5, 1fr 2fr);
}
Явный и неявный грид
Во всех примерах выше мы создавали наши колоночные (столбцовые) треки с помощью свойства grid-template-columns
, в то время как грид самостоятельно создавал строки (ряды, полосы) для любого контента там, где это требовалось. Эти строки создавались в неявном гриде. Явный грид состоит из строк и колонок, которые мы определяем с помощью grid-template-columns
и grid-template-rows
. Если Вы размещаете что-нибудь вне рамок определенного данными свойствами грида или в зависимости от контента требуется большее количество грид-треков, грид создает строки и колонки в виде неявного грида. Размер подобных треков по умолчанию задается автоматически в зависимости от находящегося в них контента.
Вы также можете задать размер треков, создаваемых в виде неявного грида с помощью свойств grid-auto-rows
и grid-auto-columns
.
В примере ниже мы задаем grid-auto-rows
, чтобы треки, создаваемые в неявном гриде были высотой 200 пикселей.
<div class="wrapper">
<div>One</div>
<div>Two</div>
<div>Three</div>
<div>Four</div>
<div>Five</div>
</div>
.wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: 200px;
}
Масштабирование треков и minmax()
При задании размеров явного грида или при определении размеров автоматически создаваемых колонок или строк может возникнуть следующая ситуация: мы хотим определить для треков минимальный размер, но при этом быть уверенными, что при необходимости треки растянутся, чтобы вместить весь добавленный в них контент. Например, нам нужно, чтобы строки никогда не становились меньше 100 пикселей, но если контент занимает, скажем, 300 пикселей в высоту, мы хотим, чтобы строка тоже стала 300 пикселей.
Для подобных ситуаций в Grid предусмотрено решение с помощью функции minmax()
. В следующем примере minmax()
используется, как значение свойства grid-auto-rows
. Автоматически создаваемые строки будут как минимум 100 пикселей в высоту, а как максимум примут значение auto
. Использование auto
означает, что размер строки посмотрит на размер контента и растянется таким образом, чтобы вместить самый высокий элемент ячейки в этой строке.
.wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: minmax(100px, auto);
}
<div class="wrapper">
<div>One</div>
<div>Two
<p>I have some more content in.</p>
<p>This makes me taller than 100 pixels.</p>
</div>
<div>Three</div>
<div>Four</div>
<div>Five</div>
</div>
Grid-линии
Нужно заметить, что когда мы определяем грид, мы определяем грид-треки, а не грид-линии. После этого грид обеспечивает нас пронумерованными линиями, номера которых можно использовать для размещения элементов. Например, в гриде с тремя колонками и двумя рядами у нас - четыре колоночные линии.
Линии нумеруются в соответствии с режимом написания (writing mode) документа. В языках с написанием слева-направо, линия 1 - самая левая линия в гриде. В языках с написанием справа-налево, линия 1 - самая правая линия в гриде. Линиям также можно давать имена, и - не переключайтесь, дальше мы узнаем, как это делать.
Размещение элементов по линиям
В дальнейшем мы детально рассмотрим размещение элементов с помощью линий, а пока остановимся на простом способе. При размещении элемента мы ссылаемся именно на линию, а не на трек.
В следующем примере мы размещаем первые два элемента в нашем гриде из трех колоночных треков с помощью свойств grid-column-start
, grid-column-end
, grid-row-start
и grid-row-end
. Поскольку режим написания слева направо, первый элемент размещается, начиная с колоночной линии 1, и занимает пространство до колоночной линии 4, которая в нашем случае - самая правая линия грида. Наш элемент начинается со строчной линии 1 и заканчивается на строчной линии 3, таким образом занимая два строчных трека.
Второй элемент начинается с колоночной линии 1 и занимает один трек. Это поведение по умолчанию, поэтому не нужно задавать конечную линию. Элемент также занимает два строчных трека - со строчной линии 3 до строчной линии 5. Остальные элементы самостоятельно размещаются в пустых пространствах грида.
<div class="wrapper">
<div class="box1">One</div>
<div class="box2">Two</div>
<div class="box3">Three</div>
<div class="box4">Four</div>
<div class="box5">Five</div>
</div>
.wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: 100px;
}
.box1 {
grid-column-start: 1;
grid-column-end: 4;
grid-row-start: 1;
grid-row-end: 3;
}
.box2 {
grid-column-start: 1;
grid-row-start: 3;
grid-row-end: 5;
}
Не забывайте, что Вы можете использовать Grid Inspector в Firefox Developer Tools, чтобы посмотреть, как элементы размещаются по линиям грида.
Grid-ячейки
Грид-ячейка (grid cell) - наименьшая единица измерения грида, концептуально похожая на ячейку таблицы. Как мы видели в предыдущих примерах, едва грид определен для родительского элемента, дочерние элементы автоматически размещаются в каждой ячейке нашего заданного грида. На рисунке ниже первая ячейка грида выделена цветом.
Grid-области
Элементы могут занимать одну или несколько ячеек внутри строки или колонки, и подобное поведение создает грид-область (grid area). Грид-области должны быть перпендикулярными, - невозможно создать область, например, в форме буквы L. Выделенная цветом грид-область на рисунке ниже занимает два строчных трека и два колоночных.
Зазоры (Gutters)
Зазоры (Gutters) или аллеи (alleys) между грид-ячейками можно создать с помощью свойств grid-column-gap
и grid-row-gap
, или с помощью сокращенного свойства grid-gap
. В примере ниже мы создаем зазор в 10 пикселей между колонками и в 1em
между строками.
.wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-column-gap: 10px;
grid-row-gap: 1em;
}
<div class="wrapper">
<div>One</div>
<div>Two</div>
<div>Three</div>
<div>Four</div>
<div>Five</div>
</div>
Любое пространство, которое занимают зазоры, добавляется в начало эластичных треков, задаваемых с помощью fr
, поэтому зазоры используются для регулирования размеров и действуют как регулярные грид-треки, хотя что-то разместить в них нельзя. В терминах расположения элементов по грид-линиям (line-based positioning) зазоры ведут себя так, как если бы самой грид-линии была добавлена толщина.
Вложенные гриды
Грид-элемент может быть и грид-контейнером. В следующем примере у нас есть созданный ранее трехколоночный грид, в котором размещены два элемента. В данном случае у первого элемента есть несколько подэлементов. Поскольку эти подэлементы не являются прямыми потомками грида, они не участвуют в структуре грида и отображаются в соответствии с нормальным потоком документа.
<div class="wrapper">
<div class="box box1">
<div class="nested">a</div>
<div class="nested">b</div>
<div class="nested">c</div>
</div>
<div class="box box2">Two</div>
<div class="box box3">Three</div>
<div class="box box4">Four</div>
<div class="box box5">Five</div>
</div>
Если мы задаем для box1
значение display: grid
, то можем написать для него структуру треков, и он тоже станет гридом, а его дочерние элементы будут размещены внутри этого нового грида.
.box1 {
grid-column-start: 1;
grid-column-end: 4;
grid-row-start: 1;
grid-row-end: 3;
display: grid;
grid-template-columns: repeat(3, 1fr);
}
В данном случае вложенный грид не связан с родительским. Как Вы можете видеть, он не наследует значение свойства grid-gap
родительского элемента и линии вложенного грида не выравниваются по линиям родительского грида.
Подгрид (Subgrid)
В спецификации гридов уровня 2 есть функциональность, называемая подгридом (subgrid) , которая позволит нам создавать вложенные гриды, использующие структуру треков родительского грида.
Примечание. Эта функция поставляется в браузере Firefox 71, который в настоящее время является единственным браузером для реализации subgrid.
В приведенном выше примере мы можем отредактировать вложенный грид, изменив grid-template-columns: repeat(3, 1fr)
, на grid-template-columns: subgrid
. Вложенный грид будет использовать родительскую структуру треков, чтобы разместить свои дочерние элементы.
.box1 {
grid-column-start: 1;
grid-column-end: 4;
grid-row-start: 1;
grid-row-end: 3;
display: grid;
grid-template-columns: subgrid;
}
Размещение элементов с помощью z-index
Несколько грид-элементов могут занимать одну и ту же ячейку. Если вернуться к нашему примеру с элементами, размещенными по номерам линий, мы можем сделать так, чтобы два элемента перекрывались:
<div class="wrapper">
<div class="box box1">One</div>
<div class="box box2">Two</div>
<div class="box box3">Three</div>
<div class="box box4">Four</div>
<div class="box box5">Five</div>
</div>
.wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: 100px;
}
.box1 {
grid-column-start: 1;
grid-column-end: 4;
grid-row-start: 1;
grid-row-end: 3;
}
.box2 {
grid-column-start: 1;
grid-row-start: 2;
grid-row-end: 4;
}
Элемент box2
теперь перекрывает box1
, и отображается сверху, поскольку в исходном коде находится ниже.
Управление порядком отображения
Порядком, в котором элементы накладываются друг на друга, можно управлять с помощью свойства z-index
- точно так же, как в случае с позиционированными элементами. Если задать box2
значение z-index
, меньшее, чем у box1
, в стеке он отобразится под элементом box1
.
.wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: 100px;
}
.box1 {
grid-column-start: 1;
grid-column-end: 4;
grid-row-start: 1;
grid-row-end: 3;
z-index: 2;
}
.box2 {
grid-column-start: 1;
grid-row-start: 2;
grid-row-end: 4;
z-index: 1;
}
Что дальше?
В данной статье мы очень кратко рассмотрели спецификацию Grid Layout. Поиграйте с примерами кода и переходите к следующей части нашего гида, где мы детально покопаемся в недрах CSS Grid Layout.