Данный материал является вольным переводом статьи:
Ire Aderinokun The Holy Grail Layout with CSS Grid
Материал вычитывал: Михаил Синяков
Хотя CSS Grid Layout Module пока еще находится в статусе редакторского черновика, но завершение уже близко. Мы можем включить модуль в некоторых браузерах для тестирования и выяснить, какие ошибки реализация имеет на данный момент.
CSS Grid Layout реально сложен, даже больше, чем Flexbox. Он имеет 17 новых свойств и вводит множество новых концепций на всем пути написания CSS. В попытке понять новую спецификацию, я использовала модуль для создания макета «Святой Грааль».
Что такое макет «Святой Грааль»?
Святой Грааль это макет, который состоит из четырех разделов — header, footer, основное содержимое и две боковых колонки, по одной с каждой стороны. Макет так же придерживается следующих правил:
- «Плавающая» ширина центральной части и фиксированная ширина сайдбаров
- Центральная часть в разметке должна идти раньше, чем два сайдбара (но после header’а)
- Все три колонки должны быть одинаковой высоты, вне зависимости от содержимого
- Футер должен быть всегда прижат к низу, даже если контент не заполняет вьюпорт
- Макет должен быть отзывчивым, все разделы должны схлопываться в один столбец на маленьких экранах
Сделать такое при помощи обычного CSS без хаков довольно сложно.
Решение с использованием CSS Grid
Вот такое решение я придумала используя CSS Grid. Во-первых, разметка:
<body class="hg">
<header class="hg__header">Title</header>
<main class="hg__main">Content</main>
<aside class="hg__left">Menu</aside>
<aside class="hg__right">Ads</aside>
<footer class="hg__footer">Footer</footer>
</body>
И CSS, всего 31 строка!
.hg__header { grid-area: header; }
.hg__footer { grid-area: footer; }
.hg__main { grid-area: main; }
.hg__left { grid-area: navigation; }
.hg__right { grid-area: ads; }
.hg {
display: grid;
grid-template-areas: "header header header"
"navigation main ads"
"footer footer footer";
grid-template-columns: 150px 1fr 150px;
grid-template-rows: 100px
1fr
30px;
min-height: 100vh;
}
@media screen and (max-width: 600px) {
.hg {
grid-template-areas: "header"
"navigation"
"main"
"ads"
"footer";
grid-template-columns: 100%;
grid-template-rows: 100px
50px
1fr
50px
30px;
}
}
Разбор
Как я уже упоминала, макет сделанный при помощи CSS Grid может быть очень сложным. Однако для создания этого макета я использовала только 4 из 17 новых свойств.
grid-area
grid-template-areas
grid-template-columns
grid-template-rows
Мое решение, по созданию макета «Святой Грааль» при помощи CSS Grid можно разбить на пять шагов.
1. Определение сетки
Первое, что мы хотим сделать, это определить области сетки, к которым мы можем обратиться через псевдоним. Делается это при помощи свойства grid-area
.
.hg__header { grid-area: header; }
.hg__footer { grid-area: footer; }
.hg__main { grid-area: main; }
.hg__left { grid-area: navigation; }
.hg__right { grid-area: ads; }
Затем, используя свойство grid-template-areas
мы можем расположить элементы на сетке интуитивным и визуальным способом. Свойство grid-template-areas
принимает список из строк разделенных пробелами. Каждая строчка представляет собой ряд. В каждой строке, у нас есть список областей сетки разделенных пробелами. Каждая область сетки занимает один столбец. Так что, если мы хотим, чтобы область охватила два столбца мы определяем ее дважды.
В макете «Святой Грааль» у нас есть 3 столбца и 3 ряда. Header и footer занимают 3 колонки, в то время как другие области охватывают по 1 колонке каждый.
.hg {
display: grid;
grid-template-areas: "header header header"
"navigation main ads"
"footer footer footer";
}
С помощью этой разметки мы получим следующий результат.
2. Определение ширины столбцов
Далее, мы хотим определить ширину столбцов. Она определяется при помощи свойства grid-template-columns
. Это свойство принимает разделенный пробелами список. Поскольку у нас 3 колонки, то и ширину мы определяем 3 раза.
grid-template-columns: [column 1 width] [column 2 width] [column 3 width];
В макете «Святой Грааль» мы хотим видеть 2 сайдбара по 150 пикселей каждый.
.hg {
grid-template-columns: 150px [column 2 width] 150px;
}
Также мы хотим, чтобы средний столбец занимал оставшуюся часть пространства. Мы можем сделать это при помощи новой единицы измерения fr
. Она обозначает долю свободного пространства в сетке. В нашем случае добавляется еще и ширина сайдбаров, в сумме 300px.
.hg {
grid-template-columns: 150px 1fr 150px;
}
Сейчас наш макет выглядит следующим образом.
3. Определение высоты рядов
Теперь нам нужно определить высоту рядов. Подобно тому, как мы определяем ширину столбцов при помощи grid-template-columns
, мы определяем высоту при помощи grid-template-rows
. Это свойство принимает разделенный пробелами список содержащий высоту для каждого ряда в нашей сетке. Хотя мы можем записать его на одной строке, я думаю, лучше и визуально более понятно, будет написать по одному ряду в строку.
.hg {
grid-template-rows: 100px
1fr
30px;
}
Таким образом, высота header будет равняться 100px, высота footer 30, а средний ряд (основное содержимое и две боковые панели) займет оставшуюся свободную часть.
4. Прижатый footer
В данном макете мы хотим, чтобы футер всегда находился в нижней части экрана, даже если содержимого на странице мало. Для этого установим минимальную высоту элемента .hg
равной высоте вьюпорта.
.hg {
min-height: 100vh;
}
Поскольку мы указали, что средний ряд должен занимать оставшуюся часть свободного пространства он растягивается и заполняет экран.
5. Делаем макет отзывчивым
И, наконец, мы хотим сделать макет отзывчивым. На небольших устройствах все элементы сетки должны отображаться в одном столбце, один за другим. Для этого нам необходимо переопределить 3 свойства, которые мы определили ранее grid-template-areas
, grid-template-columns
и grid-template-rows
.
Во-первых, мы хотим чтобы все элементы в сетке были в одном столбце в определенном порядке.
@media screen and (max-width: 600px) {
.hg {
grid-template-areas: "header"
"navigation"
"main"
"ads"
"footer";
}
}
Далее, мы хотим чтобы все элементы растянулись на всю ширину сетки.
@media screen and (max-width: 600px) {
.hg {
grid-template-columns: 100%;
}
}
И наконец, нам нужно сбросить высоту для каждой из строк. Все строки, кроме основного ряда, имеют определенную высоту.
@media screen and (max-width: 600px) {
.hg {
grid-template-rows: 100px /* Header */
50px /* Navigation */
1fr /* Main Content */
50px /* Ads */
30px; /* Footer */
}
}
Вот и все! Вы можете посмотреть демо по этой ссылке, а так же исходники.