От автора: статья нашего гостя, Оливера Уильямса. Оливер уже давно работает с макетом CSS Grid и кое-чему научился за это время. В этой статье он расскажет нам про концепции, которые он изучил. Мне нравится сама идея изучения макета путем разбития его на небольшие куски. Так проще изучать что-то крупное.
CSS Grid появится в браузерах в начале 2017 года. А пока новый год еще не наступил для работы с таким макетом необходимо вручную включать сетку в браузере. В ночной сборке Firefox сетка активирована по умолчанию. Лучше всего сетка пока что реализована в Chrome Canary. Однако в Firefox есть очень ценное дополнение CSS Grid Inspector, которое показывает линии сетки. На данный момент это единственный инструмент такого рода.
Для активации сетки в Chrome необходимо перейти по адресу «chrome://flags», найти и активировать поле «Enable experimental Web Platform features». В IE и Edge есть устаревшая реализация сеток, отличающаяся от текущей спецификации, из-за чего не рекомендуется экспериментировать с ней.
Нельзя создавать элементы сетки в форме блоков тетриса
Вы сами можете довольно быстро реализовать такой макет.
Сетку придумали, чтобы использовать вместе с flexbox, а не вместо него
Сетка и flexbox очень похожи. Вы могли видеть, как некоторые используют flexbox для создания сеточных систем, но flexbox задумывался не для этого. Советую прочитать статью Джейка Арчибальда не используйте flexbox для полного макетирования страниц.
Стоит вот о чем подумать:
flexbox создан для макетирования в одной плоскости (ряди или колонки);
CSS Grid создан для макетирования в двух плоскостях.
Или как выразилась Рэйчел Эндрюс: «Flexbox изначально задумывался для макетирования элементов в одном измерении. Ряды ИЛИ колонки. Grid спроектирован для макетирования в двух измерениях. Рядах И колонках.»
Функционал обоих методов можно комбинировать. Ячейки сетки можно делать флекс-контейнерами, а флекс-элементы можно превращать в сетки.
Разберем один хороший пример. Нам необходимо центрировать по вертикали текст внутри ячейки сетки и сделать так, чтобы фон покрывал всю ячейку целиком, будь то цвет, градиент или изображение. Можно взять свойство align-items со значением center, но тогда фон не будет покрывать всю площадь элемента. По умолчанию свойство align-items принимает значение stretch. Если значение изменить, фон больше не будет заполнять все пространство. Давайте оставим значение stretch, а ячейку сетки превратим в флекс-контейнер.
1 2 3 4 5 6 7 8 |
.grid { align-items: stretch; } .griditem { display: flex; align-items: center; } |
Отрицательная нумерация строк – очень полезная штука
Представьте CSS Grid фреймворк с сеткой в 12 колонок. На маленьких экранах мы не уменьшаем число колонок, а заставляем контент занимать все 12 колонок разом, тем самым создавая ощущение, что используется всего одна колонка на всю ширину экрана.
То же самое можно провернуть и в grid:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
/* Для маленьких экранов */ .span4, .span6, .spanAll { grid-column-end: span 12; } /* Для больших экранов */ @media (min-width: 650px) { .span4 { grid-column-end: span 4; } .span6 { grid-column-end: span 6; } } |
Метод вполне нормальный. Однако в CSS grid точно так же можно легко изменить количество колонок. Задав значение -1, вы всегда будете знать, что контент занимает всю свободную область.
1 2 3 4 |
/* Для маленьких экранов */ .span4, .span6, .spanAll { grid-column-end: -1; } |
Для больших экранов вам может понадобиться больше двенадцати колонок. Для мобильных устройств – где-то в районе от одной до четырех. Значение grid-template-columns легко можно менять с помощью медиа запроса.
1 2 3 4 5 6 7 8 9 |
.grid { grid-template-columns: 1fr 1fr; } @media (min-width: 700px) { .grid { grid-template-columns: repeat(12, 1fr); } } |
Бывают такие элементы, которые необходимо растянуть на всю ширину экрана на любом устройстве. Это могут быть хедер, футер или какие-либо баннеры. Для маленьких экранов можно написать:
1 2 3 |
.wide { grid-column: 1 / 3; /* начинаем на 1, заканчиваем на 3 */ } |
Однако после выполнения медиа запроса эти элементы будут занимать только первые две колонки из 12. Можно было бы добавить новое значение 13 для grid-column-end в этом же запросе, но есть метод куда проще. Просто установите конечное значение в -1, и элемент растянется на все колонки. Пример:
1 2 3 |
.wide, .hero, .header, .footer { grid-column: 1 / -1; } |
Области сетки задают неявные имена линий
Есть два способа размещения контента в сетке – по именам областей шаблона сетки и по номерам линий. Однако оба метода можно использовать в одной сетке. Можно использовать неявные имена линий, которые создаются каждый раз, когда вы задаете новую область.
1 2 3 |
.grid { grid-template-areas: "main main sidebar sidebar"; } |
Код выше, сам того не хотя, создал четыре именованные строки: main-start, main-end, sidebar-start и sidebar-end.
Может пригодиться, если вам нужно, чтобы контент перекрывал несколько ячеек, или чтобы контент вылезал за область подячейки в одной из областей сетки.
Существует еще один способ объявления областей в сетке
Области сетки задают имена линиям, так же и имена линий могут создавать новые области в сетке. Синтаксис объявления области:
1 2 3 4 5 6 |
.grid { grid-template-areas: "header header header" "main main sidebar" "footer footer footer"; } |
Синтаксис может сильно разрастись, если в вашем дизайне много пустых областей. Вы можете даже не догадываться, что существует еще один способ создания областей в сетке. Мы можем присваивать совершенно любые имена линиям в сетке, но если придерживаться шаблона [name-start] и [name-end], можно создавать новые области. Пример:
1 2 3 4 5 6 7 8 9 10 |
.grid { display: grid; grid-template-columns: 20px 100px [main-start] 1fr [main-end] 100px 20px; grid-template-rows: 100px [main-start] 100px [main-end] 100px; } .griditem1 { background-color: red; grid-area: main; } |
Скорее всего, вы не будете создавать макет целой страницы с помощью такого метода. Однако если вы хотите совместить два метода размещения элементов, grid-area и нумерацию линий, просто знать о нем не помешает.
Создавайте блоки одинаковых размеров при помощи vmin
CSS grid позволяет использовать любые единицы измерения для указания размеров рядов и колонок. Хотите, чтобы колонки были одинаковые и в то же время адаптивные? Если вы хотите, чтобы контент изменялся вместе с контейнером, можете воспользоваться единицами измерения vw и vh.
1 2 3 4 |
.grid { grid-template-columns: repeat(5, 20vw); grid-template-rows: repeat(5, 20vh); } |
Метод отлично сработает на десктопе и ноутбуках, однако на мобильных устройствах, где высота экрана превышает ширину, контент не будет вмещаться, тем самым создавая горизонтальную полосу прокрутки. Дадли Стори недавно написал статью о полезности мало известных единиц измерения vmin. Единицы измерения вычисляются в виде процента от ширины экрана в портретной ориентации и высоты в альбомной ориентации.
1 2 3 4 5 6 7 8 9 |
.gridcontainer { display: grid; width: 100vw; height: 100vh; justify-content: center; align-content: center; grid-template-columns: repeat(5, 20vmin); grid-template-rows: repeat(5, 20vmin); } |
Мы получили одинаковые блоки, адаптирующиеся под любой размер экрана.
Абсолютное позиционирование
При абсолютном позиционировании ячейки сетки, ее можно спозиционировать не относительно своего контейнера (т.е. всей сетки), а относительно стартовых и конечных линий заданной колонки и строки. Свойство position: absolute удаляет элемент из структуры документы (элемент игнорируется другими элементами). Свойство position: absolute очень полезно в тех случаях, когда необходимо наложить контент поверх ячеек сетки, не нарушая алгоритм авторазмещения. Автоматическое размещение элементов в сетке делает так, чтобы ячейки не налегали друг на друга. Обратное возможно только, если явно прописать grid-column-start и grid-row-start для всех ячеек.
Удалите position: absolute; у блока div в примере ниже и подумайте, сколько раз вам пришлось бы объявлять свойства grid-column и grid-row вручную!
Сортировка работает не так, как вы могли думать
Если вы работали со свойством order во flexbox, то вы уже это знаете. У всех элементов сетки по умолчанию задано значение order: 0. То есть если указать элементу order: 1, то он не станет первым.
Для сдвига элементов влево можно использовать отрицательные значения.
Лимит функции minmax
Хотите, чтобы колонки поровну делили свободное пространство, пока они не достигнут максимальной ширины? Вы могли сразу же подумать о функции minmax():
1 2 3 4 |
.grid { display: grid; grid-template-columns: repeat(3, minmax(1fr, 300px)); } |
К сожалению, код выше не сработает. Если максимальное значение меньше минимального, код будет проигнорирован. В функции minmax() нельзя использовать единицы измерения fr в минимальном значении. Значение auto в свойствах grid-template-columns и grid-template-rows растянет строку или колонку на весь контейнер.
Можно указать max-width контента:
1 2 3 4 5 6 7 8 |
.grid { display: grid; grid-template-columns: repeat(3, auto); } .item { max-width: 300px; } |
На такое поведение minmax() могут быть веские причины и определенные способы применения, о которых я не думал. Даже так, я написал целый пост на сайте Medium Что я ненавижу в Grid.
Все становится намного легче, если именовать линии в сетке
Это можно делать разными способами. Если вы любите стучать по клавиатуре, можете давать линиям несколько имен.
1 2 3 |
.grid { grid-template-columns: [col1-start] 1fr [col1-end col2-start] 1fr [col2-end]; } |
Самый простой способ именования – автоматическая нумерация. Не нужно набирать [col2], можно просто написать col и номер.
1 2 3 |
.griditem1 { grid-column-start: col 2; } |
С помощью ключевого слова span мы можем забыть о нумерации линий и начать думать о том, с какой и по какую колонки пустить контент.
1 2 3 4 5 6 7 |
.grid { grid-template-columns: repeat(4, [col] 100px); } .griditem1 { grid-column: col 2 / span 2; } |
С единицами измерения fr ничего не нужно считать
Скажем, нам нужно разбить сетку на четыре равных колонки. Это легко сделать с помощью процентов. Нужно всего лишь написать grid-template-columns: 25% 25% 25% 25%.
А что будет, если мы захотим воспользоваться свойством grid-gap? Grid-gap: 10px. У нас три разделителя между колонками, то есть ширина станет 100% + 30px. Появится горизонтальная прокрутка, а часть контента уйдет за пределы экрана вправо. Тут можно было бы использовать функцию calc(), но с единицами fr все намного проще: grid-template-columns: 1fr 1fr 1fr 1fr.
Что я еще ненавижу в сетках
Нельзя заставить алгоритм автоматического размещения оставить некоторые колонки или строки пустыми.
С помощью свойства grid-gap очень легко контролировать отступы в контенте. Для разделения колонок и рядов можно использовать отдельные свойства grid-row-gap и grid-column-gap, но у них должны быть одинаковые значения. Если мы хотим сделать отступ между первой и второй строкой в 10 пикселей, а между второй и третьей строкой в 50px, нам ничего не остается, кроме как создать несколько дополнительных строк и оставить их пустыми.
Вы могли видеть, как в синтаксисе grid-template-area используются точки:
1 2 3 4 5 6 |
grid-template-rows: "header header header" "main main main" " . . ." "secondary secondary secondary" "footer footer footer"; |
С их помощью можно очень просто заставить алгоритм автоматического размещения не вставлять в эти области элементы. К сожалению, это не работает. Синтаксис всего лишь говорит, что мы не хотим включать третью строку в именованную область сетки. Но алгоритм все равно все сделает по-своему.
Несколько советов по дизайну: необязательно иметь 12 колонок (а колонки необязательно должны быть одного размера)
По умолчанию в веб-дизайне используется 12 колонок. Bootstrap использует 12 колонок, как и другие фреймворки. И это неспроста: 12 делится одновременно и на 3, и на 4, что дает большую гибкость при размещении контента на странице. Контент можно разделить поровну на 12, 6, 4, 3 части или пополам.
Некоторые любят работать так, как уже привыкли, используя одну и ту же сетку во всех проектах. Однако нет нужды делать колонок больше, чем вам необходимо. Сетку нужно строить так, чтобы она подходила под контент и макет, а не делать один вариант для всего.
Посмотрите примеры на Gridset. Gridset – полезный инструмент для создания сеток. Но после выхода нативного модуля сеток для CSS этот инструмент вам больше не понадобится. Там можно найти несколько замечательных примеров сеток.
Я взял на себя смелость переделать один из макетов при помощи CSS grid:
Автор: Oliver Williams
Источник: //css-tricks.com/
Редакция: Команда webformyself.