Поразительный CSS Grid Area

Stas Bagretsov
8 min readApr 25, 2019

CSS Grid Area (ну или области, я предпочитаю оригинальное название в этом случае) это на самом деле очень полезный инструмент при работе с гридами, конечно сначала они введут в путаницу, но потом вашему восхищению не будет предела.

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

Перевод статьи CSS Grid Areas are amazing

👉Мой Твиттер — там много из мира фронтенда, да и вообще поговорим🖖. Подписывайтесь, будет интересно: ) ✈️

Когда я впервые узнал о CSS Grid раскладке и новых возможностях, которые она даёт CSS разработчикам, я тут же сильно заинтересовался этим всем делом. Я был просто в восторге от перспективы того, что можно будет избавиться от этих всех несемантических div контейнеров, которые нужны в Bootstrap и Foundation, заменив их на чистый, семантический HTML и оставить разметку полностью на CSS, так как это всегда и должно было быть.

Но когда я разговаривал с другими разработчиками, которые не сильно тревожились о семантической разметке, то я часто получал ответ в стиле, “Я уже знаю как работать с сеткой и мне реально не надо учить что-то совершенно новое прямо сейчас… я получу что-то практическое или я просто вернусь к началу и будут те же яйца, только в профиль? Что я могу сделать на CSS Grid такого, что я не могу уже сейчас сделать на простой системе сеток?

Сегодня я отвечу вам на этот вопрос двумя словами: “Grid Areas”.

Треки и линии

В CSS Grid раскладке сетка состоит из треков и линий. Трек это обобщающее определение для строк и колонок. Как вы уже могли предположить, “линии” это разделители между треками. Мы размечаем нашу сетку как треки с grid-template-rows и grid-template-columns, затем мы прикрепляем наши грид-элементы к сетке по линиям с grid-row и grid-column.

Во многих случаях, возможно даже почти во всех, треки и линии это всё, что вам нужно, чтобы разметить сетку. Особенно для маленьких областей с динамическим контентом, таких как сетка для результатов поиска или списка друзей, вы можете зачастую просто использовать grid-template-columns, чтобы указать колонки и использовать grid-auto-rows, чтобы указать то, какой высоты будут новые строки и дальше уже позволить магии авто-размещения CSS Grid’ов сделать своё дело.

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

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

Вот HTML:

<main>
<h1 class="display-name">...</h1>
<section class="avatar"><img src="..."></section>
<section class="about">...</section>
<section class="posts">...</section>
</main>

А вот CSS:

main {
display: grid;
grid-template-columns: repeat(5, 1fr);
}
.display-name {
grid-row: 1 / 2;
grid-column: 3 / 6;
}
.avatar {
grid-row: 1 / 3;
grid-column: 1 / 3;
}
.about {
grid-row: 3 / 4;
grid-column: 1 / 3;
}
.posts {
grid-row: 2 / 5;
grid-column: 3 / 6;
}

Правило grid-template-columns для грид контейнера указывает треки для колонок, а grid-row и grid-column указывают грид-элементам какими линиями им ограничиваться.

И конечно же, это будет работать. Но тут есть некоторые недочеты:

Гладя на кучу чисел сложновато визуализировать ваш грид и я частенько копаюсь с этими номерами линий, чтобы всё выглядело правильно. Это не проблема именно CSS Grid и если быть честным, это куда проще, чем копаться с паддингами, маргинами и значениями флоатов с flex-grow, что стоит отметить.

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

Тут очень много повторений. Относясь к предыдущей теме, если вам надо просто добавить колонку слева, ну к примеру, на сайдбар, то вам нужно будет найти все grid-row: 1/… и обновить их, каждую, с 1 на 2. На сложных шаблонах это будет ещё хуже.

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

Но спасибо, что создатели спеки о CSS Grid дали нам восхитительный функционал, который помогает решать нам эти проблемы: Grid Areas!

Areas

grid-area это прямоугольное сечение сетки, ограниченное грид линией с каждой стороны (так, 4 грид линии, 2 горизонтальные и 2 вертикальные).

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

/*
grid-area: row-start / col-start / row-end / col-end;
*/


.about {
grid-area: 3 / 1 / 5 / 3;
}

Но это на самом деле не решает проблем указанных выше. Вы вполне можете заявить о том, что так даже хуже, потому что это сложнее читается. (Какое число отвечает за grid-row-end?)

Так что вместо этого и вместо всех этих треков и линий, дайте мне показать вам фичу CSS Grid, которая полностью покорила меня, как только я её увидел: grid-template-areas!

main {
display: grid;
grid-template-areas:
"avatar avatar name name name"
"avatar avatar posts posts posts"
"about about posts posts posts"
". . posts posts posts"
;
}
.display-name {
grid-area: name;
}
.avatar {
grid-area: avatar;
}
.about {
grid-area: about;
}
.posts {
grid-area: posts;
}

Посмотрите на это.

Вместо указания строк и колонок, мы разложили весь грид визуально с именованными грид-областями, используя то, что Рэйчел Эндрю называет “ASCII art” методом для описания грида. Тут каждая строка это row, заключенный в кавычки (“…”), а каждой ячейке даётся имя грид-области которой она принадлежит. Если ячейке не требуется принадлежность к какой-либо области, то просто поставьте точку (ну или несколько точек, это уже стилистические предпочтения) на это её место. Ячейки разделены пробелом, в случае с лишним пробелом, он учитываться не будет, что делает форматирование грида визуально очень простым.

Каждая грид область определяется всеми ячейками, которые носят её имя. Как вы уже могли предположить, ваши области должны быть прямоугольными и непрерывными; без “тетрисных” блоков и так называемых кротовых нор.

После того, как вы указали все грид области, вы можете прикрепить к ним ваши грид элементы, выставив grid-area для элемента, указав там имя области в котором его расположить.

Обратите внимание, что тут нет grid-template-columns или grid-template-rows; По-дефолту, треки просто выводятся из ASCII разметки. (Ну не круто же?) Со всем выше сказанным, вы до сих пор можете использовать эти правила, если вам надо; зачастую это всё ещё необходимо на выставления размеров. Вы также можете использовать сокращения в grid-template, чтобы указать все три правила за раз. В этом сокращении, вы по желанию можете задать каждой строке высоту, сразу же после её описания в ASCII, а дальше, если вам нужно указать размеры колонок, вы можете добавить слэш после последней строки и указать конкретные размеры прямо под нужными колонками:

grid-template:
"avatar avatar name name name" 2rem
"avatar avatar posts posts posts"
"about about posts posts posts" 6rem
"...... ...... posts posts posts"
/ 2fr 10px 3fr 1fr 5vw
;

ИМХО, это куда более читабельно, визуально понятно и в конце концов поддерживаемо для статичных грид раскладок, чем длинные списки указания грид линий.

Адаптивность и семантика

Если бы меня спросили, что по моему мнению самое клевое в CSS Grid, то я бы ответил вот что: самым большим плюсом для веба, является то, что с CSS Grid легко достигнуть адаптивности без вреда семантике.

В пользовательском профайле выше, внимательный читатель мог заметить кое-что странное: в HTML, порядок секций был таким:

display name

avatar

about

posts

Но в грид разметке, аватар идёт первым, следом идет отображение имени справа, ниже размещена секция информации и список постов ниже справа. Более того, секция постов частично параллельно находится на уровне аватара и секции информации.

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

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

Это затрагивает семантический аспект, но что поделать с адаптивностью?

Хорошо, давайте посмотрим что случится, если пользователь сузит шаблон до мобильных размеров, в частности вертикальную ориентацию на маленьких экранах. (Может быть вы уже читаете эту статью с мобилки, так что вам даже представлять не надо!) Не выглядит круто. Так что давайте добавим брейкпоинт медиа запроса, скажем, на 800px, чтобы перестроить наш шаблон, чтобы он отображал порядок секций, указанный выше. Готовы? Вот код:

@media(max-width: 800px) {
main {
grid-template-areas:
"name"
"avatar"
"about"
"posts"
;
}
}

Бах! Вот оно! Вот всего то, что нужно сделать!

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

@media(min-width: 1500px) {
main {
grid-template-areas:
"avatar name posts"
"avatar about posts"
". . posts"
;
}
}

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

И во всех трёх версиях, HTML исходное не изменялся, так что пользователь со скринридером или веб-краулер со скрин-крэпером, увидят информацию на странице с предпочитаемом семантическом порядке.

Заключение

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

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

--

--

Stas Bagretsov

Надеюсь верую вовеки не придет ко мне позорное благоразумие. webdev/sports/books