Как стать автором
Обновить

Именование в CSS Grid

Время на прочтение12 мин
Количество просмотров19K
Автор оригинала: Rachel Andrew
Когда вы впервые изучаете, как использовать Grid-разметку, можно начать с размещения элементов на сетке по номерам линий. В этом случае необходимо следить за тем, где на сетке проходят определённые линии, и помнить о том, что последовательность их номеров меняется на противоположную, если сайт отображается для языков, которые пишутся справа налево.

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



От переводчика:
Статья двухлетней давности (2017 год), но затрагивает важные механики функционала CSS Grid, а потому кажется полезной и актуальной и на сегодняшний день.

Именование линий


Начнём с именования линий сетки. На примере ниже есть Grid с шестью явными колоночными треками и одним явным строчным треком. Элементы размещаются на сетке с помощью номеров линий.

.grid {
  display: grid;
  grid-gap: 20px;
  grid-template-rows: 20vh ;
  grid-template-columns: 1fr 2fr 1fr 2fr 1fr 2fr;
}

.header {
  grid-row: 1;
  grid-column: 1 / -1;
}

.sidebar {
  grid-row: 2;
  grid-column: 1 / 3;
}

.content {
  grid-row: 2;
  grid-column: 3 / -1;
}

Если необходимо, имена линиям можно задать внутри квадратных скобок в списке треков. Здесь важно помнить, что вы именуете линию, а не трек, который следует после неё. Назвав линии, вы можете использовать их имена вместо номеров при позиционировании элементов на сетке.

.grid {
  display: grid;
  grid-gap: 20px;
  grid-template-rows: [header-start] 20vh [header-end] ;
  grid-template-columns: [sidebar-start] 1fr 2fr [sidebar-end] 1fr 2fr 1fr 2fr;
}

.header {
  grid-row: header-start;
  grid-column: 1 / -1;
}

.sidebar {
  grid-row: 2;
  grid-column: sidebar-start / sidebar-end;
}

Имя может быть любым, кроме ключевого слова span. По причинам, о которых вы узнаете позже в этой статье, хорошей практикой является именование с использованием суффикса -start для начальных линий (не важно, это линия строки или колонки), и -end для конечных. В итоге должно получиться main-start и main-end или sidebar-start и sidebar-end.

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

.grid {
  display: grid;
  grid-gap: 20px;
  grid-template-rows: [header-start] 20vh [header-end] ;
  grid-template-columns: [full-start sidebar-start] 1fr 2fr [sidebar-end main-start] 1fr 2fr 1fr 2fr [main-end full-end];
}

.header {
  grid-row: header-start;
  grid-column: full-start / full-end;
}

.sidebar {
  grid-row: 2;
  grid-column: sidebar-start / sidebar-end;
}

.content {
  grid-row: 2;
  grid-column: main-start / main-end;
}

Этот пример демонстрирует, что вам не обязательно называть каждую отдельную линию сетки, и что всегда остаются доступны номера линий, которые можно использовать помимо имён.

Codepen 1. Именование линий

Линии с одинаковыми именами


Мы увидели как линии могут иметь несколько имён, но также встречаются ситуации, когда несколько линий имеют одинаковые имена. Это происходит, если использовать функцию repeat() и включить именованные линии в список треков. Следующий пример создаёт шесть именованных линий, поочерёдно названных col-a-start и col-b-start.

.grid {
  display: grid;
  grid-gap: 20px;
  grid-template-columns: repeat(3, [col-a-start] 1fr [col-b-start] 2fr);
}

Если при позиционировании элемента указать col-a-start, он будет помещён на первой встреченной линии с именем col-a-start (что в рассмотренном примере было бы первой линией сетки). По тому же принципу, если при позиционировании элемента указать col-b-start, он будет помещён на второй линии сетки.

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

.box3 {
  grid-row: 2;
  grid-column: col-a-start 2 / col-b-start 3;
}

Codepen 2. Линии с одинаковыми именами

Спецификация описывает это поведение как «создание именованного набора линий сетки».

Сохранение имён линий при перестроении адаптивной сетки


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

В следующем простом примере я определяю grid-колонки для узкого экрана, после чего переопределяю при ширине в 550px.

.grid {
  display: grid;
  grid-gap: 20px;
  grid-template-rows: [header-start] 20vh [header-end];
  grid-template-columns: [full-start ] 10px [sidebar-start main-start] 1fr [main-end sidebar-end] 10px [full-end];
}

@media (min-width: 550px) {
  .grid {
    grid-template-columns: [full-start sidebar-start] 1fr 2fr [sidebar-end
      main-start] 1fr 2fr 1fr 2fr [main-end full-end];
  }
}

Codepen 3. Naming things: redefining the position of named lines

Именованные области


До этого мы рассматривали только именованные линии, однако существует другой способ. Мы можем именовать grid-области.

Grid-область – это прямоугольная область, состоящая из одной или нескольких grid-ячеек. Область определяется четырьмя grid-линиями, обозначающими начальные и конечные линии для колонок и строк


Мы именуем области сетки используя свойство grid-template-areas. Это свойство описывает макет в виде ASCII-таблицы и представляет из себя набор строк, каждая из которых описывает отдельный строчный трек сетки.

.grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr 2fr) ;
  grid-template-areas: 
"head head head head head head"
"side side main main main main"
"foot foot foot foot foot foot";
}

Имена, которые мы используем в строках свойства grid-template-areas, присваиваются прямым дочерним элементам сетки с помощью свойства grid-area. Значение этого свойства, когда оно используется для присвоения имени, является так называемым пользовательским идентификатором, поэтому его не нужно заключать в кавычки

.header {
  grid-area: head;
}

.sidebar {
  grid-area: side;
}

.content {
  grid-area: main;
}

.footer {
  grid-area: foot;
}

Чтобы при описании структуры сетки с помощью свойства grid-template-areas заставить область покрывать больше одной ячейки, нужно несколько раз повторно записать её идентификатор вдоль строки или столбца. Созданная область должна быть прямоугольником, L и T-образные области недопустимы. Также можно создать только одну прямоугольную область для каждого имени – разъединённые области недопустимы. Спецификация отмечает, что:
“Непрямоугольные или разъединённые области могут быть разрешены в будущих версиях данного модуля”
Свойство grid-template-areas


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

grid-template-areas: 
"head head head head head head"
"side side main main main main"
"foot foot foot foot foot foot";
}

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

grid-template-areas: 
"head head head head head head"
"side side main main main main"
"....... ....... foot foot foot foot";
}

Codepen 4. Именованные области

Если вы еще не загрузили Firefox, чтобы воспользоваться всеми новейшими функциями Firefox DevTools Grid Inspector, рекомендую сделать это при работе с именованными областями


Демонстрация именованных областей в «Grid Inspector» браузера Firefox (Открыть оригинал)

Из именованных линий образуются области


Теперь мы подошли к интересной части всего этого праздника именований. Вы можете помнить, что когда мы рассматривали именованные линии, я предложила использовать соглашение о завершении имён линий, которое задаёт начало области с помощью -start, конец области с помощью -end. Причина этого в том, что если вы именуете линии таким образом, в итоге получите grid-область с таким именем, и в неё можно будет поместить элемент, задав это самое имя через свойство grid-area.

В следующем примере как для строк, так и для колонок я именую линии panel-start и panel-end. Это даст мне именованную область, называемую panel. Если я задам его в качестве значения свойства grid-area для элемента на странице, это поместит элемент в область, определённую данными линиями

.grid {
  display: grid;
  grid-gap: 20px;
  grid-template-columns: 1fr  [panel-start] 2fr 1fr 2fr 1fr [panel-end] 2fr;
  grid-template-rows: 10vh [panel-start] minmax(200px, auto) 10vh [panel-end];
  grid-template-areas: 
 "head head head head head head"  
 "side side main main main main" 
 ".... .... foot foot foot foot";
}

.panel {
  grid-area: panel;
}

Codepen 5. Из именованных линий образуются области

Из именованных областей образуются линии


Также мы можем сделать и обратное тому, что показано выше, используя линии, созданные из именованных областей. Каждая область создаёт четыре именованных линии, используя то же соглашение о суффиксах -start и -end. Если имеется именованная область, называемая main, её начальные и конечные строчные и колоночные линии будут называться main-start и main-end. Эти именованные линии можно использовать для позиционирования элемента.

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

.grid {
  display: grid;
  grid-template-areas: 
 "head head head head head head"  
 "side side main main main main" 
 ".... .... foot foot foot foot";
}

.panel {
  grid-column: main-start / main-end;
  grid-row: head-start / foot-end;
}

Codepen 6. Из именованных областей образуются линии

Имена линий, эквивалентные имени области


В дополнение к линиям с приставками -start и -end, для граней любой grid-области создаются линии с именем этой области. Таким образом, если имеется область main, можно использовать идентификатор main в качестве значения для свойств grid-row-start или grid-column-start, и содержимое будет располагаться от начала этой области. Если вы использовали это значение для свойства grid-row-end или grid-column-end, то выбирается конечная линия этой области. В приведённом ниже примере я растягиваю элемент .panel от начала main до конца main для колонок, и от начала main до конца foot для строк

.panel {
  grid-column: main;
  grid-row: main / foot ;
}

Codepen 7. Имена линий, эквивалентные имени области

Объяснение свойства grid-area


Полезным является знать кое-что и о свойстве grid-area. По существу, что мы делаем при использовании grid-area с таким идентификатором, как main, – так это описываем все четыре линии области. Допустимым значением для свойства grid-area также являются и номера линий

.main {
  grid-area: 2 / 1 / 4 / 3;
}

Это имеет тот же эффект, что и запись:
.main {
  grid-row-start: 2;
  grid-column-start: 1;
  grid-row-end: 4;
  grid-column-end: 3;
}

Когда вы задаете
.main {
  grid-area: main;
}

На самом деле это значит:
.main {
  grid-area: main / main / main / main ;
}

Свойство grid-area ведёт себя немного иначе, когда применяется пользовательский идентификатор, а не номер линии. При использовании номеров линий для начальных значений в свойстве grid-area, любой номер конечной линии, который вы не зададите, будет автоматически установлен на auto, следовательно, будет использоваться автоматическое позиционирование для определения места, куда поместить элемент.

Однако, если вы используете пользовательский идентификатор и пропускаете некоторые линии, они устанавливаются следующим образом

Заданы три имени линий


.main {
  grid-area: main / main / main ;
}

Если задать три имени линий, то по существу, вам не хватает grid-column-end. Если grid-column-start является пользовательским идентификатором, то этот же идентификатор задаётся и для grid-column-end. Как мы уже видели, свойство -end будет использовать конечную грань области main, поэтому если для grid-column-start и grid-column-end задано одинаковое имя, содержимое растягивается на все колонки этой области.

Заданы два имени линий


.main {
  grid-area: main / main  ;
}

Когда заданы только два имени, устанавливаются начальные линии строк и колонок. Если grid-column-start и/или grid-row-start является пользовательским идентификатором, то grid-column-end и grid-row-end устанавливается в то же значение соответственно.

Задано одно имя линии


.main {
  grid-area: main  ;
}

Установка одного имени линии это именно то, что вы делаете, когда задаёте grid-area основное имя области. В этом случае все четыре линии устанавливаются в это значение.

Примечание: Это работает и для grid-column и для grid-row.

Этот метод фактически означает, что вы можете обозначить набор колонок или строк в сетке для размещения элемента. Как значения -end для свойства grid-area устанавливаются в то же значение, что и начальные (когда опущены), так же ведут себя конечные значения и для свойства grid-column и grid-row. Это значит, что вы можете разместить элемент между начальной и конечной колоночными линиями области main, используя:

.main {
  grid-column: main  ;
}

В публикации Breaking Out with CSS Grid explained я показала, как эта возможность используется для создания полезных шаблонов проектирования полноразмерных областей, выходящих за пределы ограниченной области содержимого.

Сетка может иметь много именованных линий


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

Именование и сокращенные свойства grid и grid-template


CSS Grid имеет два сокращения, которые позволяют задавать множество grid-свойств в одном компактном синтаксисе. Лично мне оно кажется достаточно трудным для восприятия. Когда я обсуждаю это с другими разработчиками, мнения разделяются: одним они нравятся, другие предпочитают использовать отдельные свойства. Как и в случае с другими сокращениями, следует помнить, что значения свойств, которые вы в нём не используете, будут сброшены на исходные

Сокращение grid-template: создание явной сетки


Вы можете использовать сокращение grid-template для задания в одном месте сразу всех свойств явной сетки

grid-template-columns
grid-template-rows
grid-template-areas

Это значит, что вы можете одновременно определять именованные линии и именованные области. При использовании свойства, объединяющего именованные области и линии, я бы сначала определила значение свойства grid-template-areas, как указано в разделе выше.

Затем вы можете захотеть добавить имена строк. Они размещаются в начале и в конце каждой строчки значений – помните, что каждая строчка значений представляет строчный трек. Имя или имена строк должны быть внутри квадратных скобок, так же, как при именовании линий в свойстве grid-template-rows и должны быть снаружи кавычек, окружающих строку значений, определяющую строчный трек.

В примере ниже я назвала две строчные линии: panel-start идёт после линии хедера (вторая строчная линия сетки) а panel-end идёт после последней линии футера (четвёртая линия сетки с тремя строчными треками). Я также определила размер строчного трека для именованных и безымянных строк, добавив параметр в конце строки значений, описывающей этот строчный трек

.grid {
  display: grid;
  grid-gap: 20px;
  grid-template: 
" head head head head head head" 10vh 
[panel-start] "side side main main main main" minmax(200px, auto)
".... .... foot foot foot foot"  10vh [panel-end];
}

Если необходимо именовать еще и колонки, мы не можем сделать это внутри строки, поэтому нужно добавить разделитель /, после чего определить список колоночных треков. Линии именуются так же, как если бы этот список был значением свойства grid-template-columns.

.grid {  
  display: grid;
  grid-gap: 20px;
  grid-template: 
" head head head head head head" 10vh
[panel-start] "side side main main main main" minmax(200px, auto)
".... .... foot foot foot foot" 10vh  [panel-end]
/ [full-start ] 1fr  [panel-start] 2fr 1fr 2fr 1fr [panel-end] 2fr [full-end];
}

В этом примере, с которым вы можете ознакомиться в codepen ниже, я создаю дополнительный набор линий для строк и колонок, эти линии определяют область с именем panel, так как я использовала синтаксис panel-start и panel-end. Таким образом я могу разместить элемент, задав ему значение panel свойства grid-area.

На первый взгляд это выглядит довольно непонятно. Так вот, здесь мы создаем список колонок, которые выстраиваются в соответствии с нашей ASCII-таблицей, определённой выше. При желании, можно добавить пробелы между значениями, чтобы выровнять определение template-areas и template-columns.

Codepen 8. Сокращение grid-template

Сокращение grid: явная и неявная сетка


Спецификация предполагает, что если нужно определить неявную сетку отдельно, следует использовать сокращенное свойство grid вместо grid-template. Сокращение grid сбрасывает все неявные значения, которые вы не установили. Таким образом, оно позволяет устанавливать и сбрасывать следующие свойства

grid-template-columns
grid-template-rows
grid-template-areas
grid-auto-columns
grid-auto-rows
grid-auto-flow

Для наших целей использование сокращения grid будет идентично использованию grid-template, так как мы задаём неявное определение сетки. Единственное отличие будет в сбросе свойств grid-auto–*. Сокращение grid можно использовать либо для установки явной сетки и сброса неявных свойств, либо установки неявной сетки и сброса явных свойств. Делать и то и другое одновременно не имеет особого смысла

.grid {  
  display: grid;
  grid-gap: 20px;
  grid: 
" head head head head head head" 10vh
[panel-start] "side side main main main main" minmax(200px, auto)
".... .... foot foot foot foot" 10vh  [panel-end]
/ [full-start ] 1fr  [panel-start] 2fr 1fr 2fr 1fr [panel-end] 2fr [full-end];
}

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

Какой из подходов использовать?


Вы можете спросить, какой из всех этих методов лучше всего использовать для какой-то определённой задачи? Каких-то жёстких правил нет. Лично мне нравится использовать grid-template-areas для компонентов, когда работаю в своей библиотеке шаблонов. Удобно иметь перед глазами структуру компонента прямо в CSS и grid-template-areas позволяет легко опробовать разные варианты макеты, при его тестировании. Я обнаружила, что из-за настолько простого перемещения ячеек сетки, важно следить, что не нарушился визуальный и логический порядок ячеек компонента. Посетители, которые взаимодействуют с вашим сайтом с помощью клавиатуры, переключаясь между элементами кнопкой Tab, будут выбирать элементы в том порядке, в котором они определены в разметке. Убедитесь, что не забыли изменить порядок в разметке, как только определитесь с наиболее подходящим способом отображения содержимого. Чтобы узнать больше об этой проблеме, советую почитать статью CSS Grid Layout and Accessibility.

Основные правила именования


Подводя итог статьи, повторно приведу несколько основных правил, которые нужно помнить при именовании линий или областей CSS Grid:

Именование линий:

  1. Можно использовать почти любое имя (кроме ключевого слова span), однако можно использовать и область, созданную из этих линий, если их имена заканчиваются на -start и -end
  2. Линии могут иметь несколько имён, заданных внутри квадратных скобок и разделённых пробелом
  3. Несколько линий могут иметь одинаковое имя; если нужна определённая, просто добавьте после названия номер нужной линии по порядку

Именование областей:

  1. Когда определяете область с помощью grid-template-areas, форма области должна быть прямоугольной
  2. При использовании свойства grid-template-areas, каждый строчный трек грида представлен в виде строки значений и оформляется в кавычки
  3. Каждая ячейка должна быть заполнена. Если по дизайну требуется оставить некоторые ячейки пустыми, используйте для этого точку . или многоточие ... без пробелов
  4. Именованные области создают линии с таким же названием, что и у области, но с приставками -start и -end. Их можно использовать для позиционирования элементов
Теги:
Хабы:
+8
Комментарии0

Публикации

Изменить настройки темы

Истории

Ближайшие события

PG Bootcamp 2024
Дата16 апреля
Время09:30 – 21:00
Место
МинскОнлайн
EvaConf 2024
Дата16 апреля
Время11:00 – 16:00
Место
МоскваОнлайн
Weekend Offer в AliExpress
Дата20 – 21 апреля
Время10:00 – 20:00
Место
Онлайн