Продолжаем изучать обновления ЦСС: на очереди сетки
Флексбоксы закрепились в марте 2016 года: вышли из Working Draft в Candidate Recommendation, перед этим пройдя долгий путь — браузеры по-своему реализовывали Флекбоксы, поэтому за это время накопилось куча хаков, посмотрите как отрабатывает Автопрефиксер, добавляя вендорные префиксы:
.example {
display: -webkit-box; /* для старых Хромов и Сафари */
display: -ms-flexbox; /* для IE */
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
}
Но Флекбоксы не идеальны: они работают только в одном направлении. В помощь (а не на замену!) пришли Гриды, которые работают с колонками и строками одновременно.
Поддержка браузерами, кстати, неплохая: 87.4%.
И если вы думали, что сложно запомнить все свойства Флексбоксов, то с Гридами будет ещё сложнее, поэтому рассматривать будем на примерах.
Сетка рисуется через display: grid
и свойства grid-template-columns
с grid-template-rows
, где указывается размер каждой колонки (column) или строки (row).
.parent {
display: grid;
grid-template-columns: 20% 20% 20% 20% 20%; /* 5 колонок по 20% ширины */
grid-template-rows: 20% 20% 20% 20% 20%; /* 5 колонок по 20% высоты */
}
iframe: https://jsfiddle.net/rp06zgLq/36/embedded/result,html,css/
Можно ли это упростить? Да, если указывать не 20% 20% 20% 20% 20%
, а взять функцию repeat(5, 20%)
.
А можно ещё проще? Да, можно взять grid-template, где через слэш можно указать grid-template-rows / grid-template-columns
.
#grid {
display: grid;
grid-template-rows: 10% 10% 10%;
grid-template-rows: repeat(3, 10%);
grid-template-columns: 33% 33% 33% 33%;
grid-template-columns: repeat(4, 33%);
grid-template: repeat(3, 10%) / repeat(4, 33%);
}
Можно ли указывать пиксели или ремы/емы? Конечно.
Подытожим.
Во-первых, display: grid
для родителя сетки.
Во-вторых, grid-template-*
для размеров сетки. Через пробел указывается размер колонки (ширина) или строки (высота). Упростить можно через repeat(number, size)
если размеры повторяются.
В-третьих, сокращение grid-template-rows
и grid-template-columns
до grid-template: <grid-template-rows> / <grid-template-column>
.
Окей, мы получили холст, с которым можно работать. Как же его заполнять?
Для этого нужно завести детей, которые через grid-column
и grid-row
укажут их место.
Допустим, нам нужен ребёнок, который встанет на четвёртую ячейку в третьей строке.
iframe: https://jsfiddle.net/rp06zgLq/41/embedded/result,html,css/
Может ли элемент занимать несколько ячеек или колонок? Может, если через слэш указать начало и конец ячеек.
iframe: https://jsfiddle.net/rp06zgLq/43/embedded/result,html,css/
Что делать, если неудобно указывать начало и конец? Начало должно быть обязательно, но конец можно не указывать, если взять span
(в переводе "диапазон").
#child {
grid-row: 2 / span 2; /* займёт 2 строки */
grid-column: 2 / span 4; /* займёт 4 колонки */
}
Как и в случае с grid-template
, есть сокращение grid-area: <grid-row-start> / <grid-column-start> / <grid-row-end> / <grid-column-end>
.
Подытожим.
Если указать числом позицию элемента, то он встанет именно туда.
#child {
grid-column: 2; /* второй столбец */
grid-row: 3; /* третья строка */
}
Через слэш у grid-row
и grid-column
можно указать начало и конец элемента в сетке.
#child {
grid-row: 3 / 6; /* с третьей до шестой (не включая!) строки */
grid-column: 2 / 4; /* со второго до четвёртого столбца */
}
Кстати, если вы хотите большей ясности, то grid-column
и grid-row
это сокращения для grid-*-start
и grid-*-end
.
#child {
grid-row-start: 3;
grid-row-end: 6;
grid-column-start: 2;
grid-column-end: 4;
}
Вместо номера ячейки или строки можно указать размер, добавив слово span
.
#child {
grid-row-start: 3;
grid-row-end: span 2;
grid-column-start: 2;
grid-column-end: span 1;
}
Ну и, наконец, есть сокращение grid-area: <grid-row-start> / <grid-column-start> / <grid-row-end> / <grid-column-end>
для перечисленных свойств.
#child {
grid-area: 3 / span 2 / 2 / span 1;
}
Удобно ли это? Не скажу что очень. Я бы рекомендовал использовать grid-row
и grid-column
— баланс между краткостью и очевидностью.
Можно ли не указывать grid-row
и grid-column
? Да, можно просто расставить элементы внутри и они автоматически выстроятся по порядку.
iframe: https://jsfiddle.net/rp06zgLq/44/embedded/result,html,css/
Что будет, если элементов будет больше, чем ячеек? Они выпадут за пределы сетки и строки на них не будут действовать (а колонки — будут).
iframe: https://jsfiddle.net/rp06zgLq/45/embedded/result,html,css/
Что будет, если будет элемент с grid-row
или grid-column
или grid-area
? Он сдвинет обычные элементы.
iframe: https://jsfiddle.net/rp06zgLq/35/embedded/result,html,css/
Что будет, если не указывать grid-template-row
? Элементы будут автоматически выстраиваться.
iframe: https://jsfiddle.net/rp06zgLq/49/embedded/result,html,css/
Что будет, если не указывать grid-template-column
?
Элементы будут выстраиваться по границам элементов, у которых выставлен максимальный grid-column
.
iframe: https://jsfiddle.net/rp06zgLq/56/embedded/result,html,css/
Что будет, если намиксовать значения? Да ничего, выстроится всё по ним.
iframe: https://jsfiddle.net/rp06zgLq/66/embedded/result,html,css/
ЦСС Гриды — мощный инструмент, но синтаксис у них не самый очевидный.
Нужно запомнить, что в большинстве случаев достаточно display: grid
и grid-template-*
— элементы внутри выстроятся сами.
Если нужно какому-то блоку указать место или размеры, то в дело идут grid-row
и grid-column
.
Для закрепления навыков советую пройти игру Grid Garden от создателей Flexbox Froggy.
В реальной жизни Гриды ещё не так часто используются, но вдохновения можно поискать на Кодпене, например, в этой демке Марвеловского постера, там ещё используется мощное свойство clip-path
.
See the Pen MARVEL POSTER [CSS GRID] by wiltrouble (@wiltrouble) on CodePen.
Кстати, ещё Страйп рассказывал о том, как они делали бэкграунд через ЦСС Гриды и transform
.