Расположение элементов по грид-линиям с помощью CSS Grid

Перевод не завершен. Пожалуйста, помогите перевести эту статью с английского.

В статье, касавшейся основных понятий позиционирования элементов с помощью гридов, мы кратенько рассмотрели, как располагать элементы в гриде, используя номера линий. Теперь давайте детально исследуем то, как работает эта фундаментальная часть спецификации.

Собственно, начать квест по гридам со знакомства с пронумерованными линиями - логично, потому что в ситуации, когда Вы работаете с гридами, пронумерованные линии у Вас есть всегда. Линии нумеруются и для колонок, и для строк, отсчет начинается с 1. Нужно заметить, что грид индексируется в соответствии с режимом написания (writing mode) документа. В языках с написанием слева направо, таких как русский, например, линия 1 - самая левая линия грида. Если написание справа налево, то линия 1 будет, соответственно, самой правой линией в гриде. По ходу изучения недр мы детально узнаем, как гриды взаимодействуют с режимами написания, поэтому не исчезайте, впереди много интересного.

Базовый пример

В качестве крайне простого примера давайте возьмем грид с тремя треками-колонками и тремя треками-строками. Такой грид дает нам по 4 линии для каждого направления.

Внутри нашего грид-контейнера у нас есть четыре дочерних элемента. Если мы не размещаем их явным образом, эти элементы будут расположены в гриде в соответствии с правилами авторазмещения, то есть, по одному элементу - в каждой из четырех первых ячеек. Если Вы воспользуетесь Firefox Grid Highlighter , то увидете, как грид инициирует колонки и строки.

Our Grid highlighted in DevTools

.wrapper {
   display: grid;
   grid-template-columns: repeat(3, 1fr);
   grid-template-rows: repeat(3, 100px);
}
<div class="wrapper">
   <div class="box1">One</div>
   <div class="box2">Two</div>
   <div class="box3">Three</div>
   <div class="box4">Four</div>
</div>

Позиционирование элементов по номерам линий

Мы можем воспользоваться размещением по линиям (line-based placement), чтобы расположить элементы на гриде. Например, нам нужно, чтобы первый элемент начинался от левого края и занимал один трек-колонку. Пусть он также начинается с первой строчной линии,  то есть, от верхнего края грида, и занимает пространство до четвертой строчной линии.

.box1 {
   grid-column-start: 1;
   grid-column-end: 2;
   grid-row-start: 1;
   grid-row-end: 4;
}

Если Вы явно позиционируете одни элементы, другие элементы грида по-прежнему размещаются в соответствии с правилами авторазмещения. Дальше мы детально рассмотрим, как это происходит, а пока Вы и сами могли заметить, что по мере размещения одних элементов, оставшиеся элементы занимают пустые ячейки грида.

Задавая адреса для каждого элемента по отдельности, мы можем разместить все наши четыре элемента по колонкам и строкам. Заметьте, что при желании можно оставить ячейки пустыми. Одна из самых приятных вещей при работе с Grid Layout - возможность создавать негативное пространство (пустые области в макете) без кувырков через голову и прочих хаков.

<div class="wrapper">
   <div class="box1">One</div>
   <div class="box2">Two</div>
   <div class="box3">Three</div>
   <div class="box4">Four</div>
</div>
.box2 {
   grid-column-start: 3;
   grid-column-end: 4;
   grid-row-start: 1;
   grid-row-end: 3;
}
.box3 {
   grid-column-start: 2;
   grid-column-end: 3;
   grid-row-start: 1;
   grid-row-end: 2;
}
.box4 {
   grid-column-start: 2;
   grid-column-end: 4;
   grid-row-start: 3;
   grid-row-end: 4;
}

Сокращения grid-column и grid-row

Мы написали много кода, чтобы разместить каждый элемент. Неудивительно, что существуют сокращенные свойства shorthand. grid-column-start иgrid-column-end могут быть объединены в одном grid-column, а grid-row-start иgrid-row-end - в grid-row.

<div class="wrapper">
   <div class="box1">One</div>
   <div class="box2">Two</div>
   <div class="box3">Three</div>
   <div class="box4">Four</div>
</div>
.box1 {
   grid-column: 1 / 2;
   grid-row: 1 / 4;
}
.box2 {
   grid-column: 3 / 4;
   grid-row: 1 / 3;
}
.box3 {
   grid-column: 2 / 3;
   grid-row: 1 /  2;
}
.box4 {
   grid-column: 2 / 4;
   grid-row: 3 / 4;
}

Расположение элемента по умолчанию

В примерах выше мы задавали конечную линию для строки и колонки, чтобы продемонстрировать работу свойств, однако, если элемент занимает только один трек, Вы можете опустить значение grid-column-end или grid-row-end. Грид по умолчанию размещает элемент таким образом, чтобы он занимал всего один трек. Это значит, что длинная запись свойств в нашем первоначальном примере может выглядеть вот так:

<div class="wrapper">
   <div class="box1">One</div>
   <div class="box2">Two</div>
   <div class="box3">Three</div>
   <div class="box4">Four</div>
</div>
.box1 {
   grid-column-start: 1;
   grid-row-start: 1;
   grid-row-end: 4;
}
.box2 {
   grid-column-start: 3;
   grid-row-start: 1;
   grid-row-end: 3;
}
.box3 {
   grid-column-start: 2;
   grid-row-start: 1;
}
.box4 {
   grid-column-start: 2;
   grid-column-end: 4;
   grid-row-start: 3;
}

Поэтому, если мы хотим, чтобы элементы занимали только один трек, наша сокращенная запись будет выглядеть вот так, без слэша и без второго значения:

<div class="wrapper">
   <div class="box1">One</div>
   <div class="box2">Two</div>
   <div class="box3">Three</div>
   <div class="box4">Four</div>
</div>
.box1 {
   grid-column: 1 ;
   grid-row: 1 / 4;
}
.box2 {
   grid-column: 3 ;
   grid-row: 1 / 3;
}
.box3 {
   grid-column: 2 ;
   grid-row: 1 ;
}
.box4 {
   grid-column: 2 / 4;
   grid-row: 3 ;
}

Свойство grid-area

Мы можем пойти еще дальше и определить целую область с помощью одного единственного свойства – grid-area. Порядок свойств для грид-области следующий:

  • grid-row-start
  • grid-column-start
  • grid-row-end
  • grid-column-end
<div class="wrapper">
   <div class="box1">One</div>
   <div class="box2">Two</div>
   <div class="box3">Three</div>
   <div class="box4">Four</div>
</div>
.box1 {
   grid-area: 1 / 1 / 4 / 2;
}
.box2 {
   grid-area: 1 / 3 / 3 / 4;
}
.box3 {
   grid-area: 1 / 2 / 2 / 3;
}
.box4 {
   grid-area: 3 / 2 / 4 / 4;
}

Порядок значений для grid-area может показаться немного странным, он противоположен тому порядку, в котором мы, например, записываем значения для сокращенных свойств margin и padding. Но сделано это потому, что грид работает с направлениями относительно потока, определенными в спецификации CSS Writing Modes. В дальнейшем мы рассмотрим, как гриды взаимодействуют с режимами написания (writing modes), но пока давайте примем за данность, что мы имеем дело с концепцией четырех направлений относительно потока:

  • block-start (начало блока)
  • block-end (конец блока)
  • inline-start (начало строки)
  • inline-end (конец строки)

Мы работаем с русским, языком с написанием слева направо. Начало нашего блока (block-start) - верхняя строчная линия грид-контейнера, конец блока (block-end) - последняя строчная линия контейнера. Начало строки (inline-start) - самая левая колоночная линия, поскольку начало строки - это всегда точка, с которой начинается написание текста в заданном режиме написания. Конец строки (inline-end) - последняя колоночная линия грида.

Когда мы задаем нашу грид-область с помощью свойства grid-area , мы сначала определяем обе начальные линии block-start и inline-start, а затем обе конечные линии  block-end и inline-end. Поскольку мы давно работаем с физическими свойствами top, right, bottom и left, поначалу это кажется непривычным, но вполне осмысленно, если осознать, что относительно режима написания вебсайты - многонаправленные структуры.

Считая с конца

Мы также можем отсчитывать грид-линии с конца, то есть с последней (для русского языка - самой правой) колоночной и последней (самой нижней) строчной линий. Индекс этих линий будет -1, а линий непосредственно перед ними -2, и так далее. Нужно помнить, что под последней линией понимается последняя линия явного грида (explicit grid), то есть грида, определенного с помощью grid-template-columns иgrid-template-rows. Любые линии строк и колонок, добавленные неявным гридом (implicit grid) не считаются.

В примере ниже мы "перевернули" определение нашего грида, при размещении элементов задавая линии с конца, то есть, от правого и нижнего краев.

<div class="wrapper">
   <div class="box1">One</div>
   <div class="box2">Two</div>
   <div class="box3">Three</div>
   <div class="box4">Four</div>
</div>
.box1 {
   grid-column-start: -1;
   grid-column-end: -2;
   grid-row-start: -1;
   grid-row-end: -4;
}
.box2 {
   grid-column-start: -3;
   grid-column-end: -4;
   grid-row-start: -1;
   grid-row-end: -3;
}
.box3 {
   grid-column-start: -2;
   grid-column-end: -3;
   grid-row-start: -1;
   grid-row-end: -2;
}
.box4 {
   grid-column-start: -2;
   grid-column-end: -4;
   grid-row-start: -3;
   grid-row-end: -4;
}

Как растянуть элемент на длину всего грида?

Возможность адресовать и первую, и последнюю линии грида становится крайне полезной, если нам нужно растянуть элемент на всю длину грида. Сделать это можно вот так:

.item {
  grid-column: 1 / -1;
}

Зазоры (Gutters) или аллеи (Alleys)

Спецификация CSS Grid включает возможность добавлять промежутки (зазоры) между треками-колонками и треками-строками с помощью свойств grid-column-gap и grid-row-gap. Эти свойства задают промежутки, которые во многом действуют точно так же, как свойство column-gap в многоколоночных макетах.

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

<div class="wrapper">
   <div class="box1">One</div>
   <div class="box2">Two</div>
   <div class="box3">Three</div>
   <div class="box4">Four</div>
</div>
.box1 {
   grid-column: 1 ;
   grid-row: 1 / 4;
}
.box2 {
   grid-column: 3 ;
   grid-row: 1 / 3;
}
.box3 {
   grid-column: 2 ;
   grid-row: 1 ;
}
.box4 {
   grid-column: 2 / 4;
   grid-row: 3 ;
}
.wrapper {
     display: grid;
     grid-template-columns: repeat(3, 1fr);
     grid-template-rows: repeat(3, 100px);
     grid-column-gap: 20px;
     grid-row-gap: 1em;
}

Сокращенная запись для грид-зазоров

Оба свойства также можно записать с помощью свойства-сокращения grid-gap. Если задать только одно значение, то оно определит размер зазоров и между колонками, и между строками. Если мы задаем два значения, то первое используется для grid-row-gap , а второе - для grid-column-gap.

.wrapper {
     display: grid;
     grid-template-columns: repeat(3, 1fr);
     grid-template-rows: repeat(3, 100px);
     grid-gap: 1em 20px;
}

В терминах расположения элементов по грид-линиям (line-based positioning) зазоры ведут себя так, как если бы самой линии была добавлена толщина. Все, что должно было начинаться от линии, начинается от нее на расстоянии зазора, и Вы не можете адресовать зазор напрямую или поместить в него что-нибудь. Если Вам нужны зазоры, которые ведут себя, как обыкновенные треки, что же - определите трек, а не зазор.

Использование ключевого слова span 

В дополнение к возможности обращаться к начальной и конечной линии по их номерам Вы можете задать номер начальной линии, а после - количество треков, которые должен занять элемент.

<div class="wrapper">
   <div class="box1">One</div>
   <div class="box2">Two</div>
   <div class="box3">Three</div>
   <div class="box4">Four</div>
</div>
.box1 {
  grid-column: 1;
  grid-row: 1 / span 3;
}
.box2 {
   grid-column: 3;
   grid-row: 1 / span 2;
}
.box3 {
   grid-column: 2;
   grid-row: 1;
}
.box4 {
   grid-column: 2 / span 2;
   grid-row: 3;
}

Ключево слово  span также можно использовать в качестве значения grid-row-start/grid-row-end иgrid-column-start/grid-column-end. Два примера ниже создают одну и ту же грид-область. В первом примере мы задаем начальную строчную линию, а после говорим свойству, отвечающему за конечную линию: эй, мы хотим занять под этот элемент три линии. В итоге, грид-область начинается с первой линии и занимает пространство до 4-ой.

.box1 {
    grid-column-start: 1;
    grid-row-start: 1;
    grid-row-end: span 3;
}

Во втором примере поступим наоборот: зададим конечную строчную линию, а в значении свойства, отвечающего за начальную линию, напишем span 3. Это значит, что элемент должен занять три трека до заданной конечной линии. Грид-область начинается с линии 4 и занимает три трека до линии 1.

.box1 {
    grid-column-start: 1;
    grid-row-start: span 3;
    grid-row-end: 4;
}

Чтобы лучше освоиться с размещением элементов по грид-линиям, попробуйте собрать несколько распространенных макетов, располагая элементы на гридах с различным количеством колонок. Помните, что если вы не размещаете все Ваши элементы, оставшиеся располагаются в соответствии с правилами авторазмещения. В результате может получиться как раз тот макет, который Вам нужен, но не факт, и если что-то пошло не так, проверьте, определили ли Вы позицию для проблемного элемента.

Также помните, что элементы на гриде могут перекрывать друг друга, если Вы намеренно разместили их так, чтобы они друг друга перекрывали. Подобное поведение позволяет получить интересные эффекты, но, если Вы некорректно задали начальные и конечные линии, результат может неприятно Вас удивить. Firefox Grid Highlighter будет крайне полезен в процессе обучения, особенно, когда Вы строите сложные гриды.

Метки документа и участники

Внесли вклад в эту страницу: denisvovchenko, coshturnina
Обновлялась последний раз: denisvovchenko,