Я на днях обнаружил печальную вещь. Хотя стандарт css grid существует не первый год, многие до сих пор то ли не знают о нем, то ли не понимают, для чего он нужен. Я крайне редко вижу его практическое использование.
При этом существует задача, которая нормальным образом решается только через grid. Речь идет о вписывании верстки в родительский контейнер, будь то виджет или страница в целом. В итоге создание подобной верстки происходит либо с помощью костылей (если использовать обычную блочную верстку (когда ее уже пометят как obsolete?)), либо с помощью избыточного кода (если использовать flex). Давайте я покажу на пример, как это делать правильно.
Вот типичная задача - нужно сделать страницу с верхним и нижним тулбаром, и центром, который должен скроллится:
<style>
.root {
width: 100%;
height: 100%;
background-color: yellow;
}
.toolbar1 {
background-color: green;
}
.main {
background-color: grey;
}
.main-big-content {
background-color: black;
height: 2000px;
}
.toolbar2 {
background-color: cyan;
}
</style>
<div class="root">
<div class="toolbar1">
<button>button1</button>
</div>
<div class="main">
<div class="main-big-content">
</div>
</div>
<div class="toolbar2">
<button>button1</button>
</div>
</div>
Посмотрим на результат:
![](https://habrastorage.org/getpro/habr/upload_files/8b5/7ae/7f5/8b57ae7f5bd818f96b41c58e88394517.png)
Разумеется, все неправильно! Нижний тулбар не виден. Ну ок, добавим overflow к центру:
.main {
background-color: grey;
overflow: auto,
}
![](https://habrastorage.org/getpro/habr/upload_files/0b4/2a1/e8a/0b42a1e8a27c80d6a354725bd2c291b8.png)
Никакого эффекта.
Что ж, давайте использовать flex. Для этого придется усложнить код, добавив flex-direction: column, flex: 1 и т. д.:
.root {
width: 100%;
height: 100%;
background-color: yellow;
display: flex;
flex-direction: column
}
.toolbar1 {
background-color: green;
}
.main {
background-color: grey;
overflow: auto;
flex: 1;
}
.main-big-content {
background-color: black;
height: 2000px;
}
.toolbar2 {
background-color: cyan;
}
![](https://habrastorage.org/getpro/habr/upload_files/771/56a/500/77156a5002401f5a701c206dc979b7e8.png)
Да что за ерунда? А, ну конечно. Body тоже скроллится. Ладно, добавим ограничителей:
html,body {
height: 100%;
padding: 0px;
margin: 0px;
}
![](https://habrastorage.org/getpro/habr/upload_files/6d9/96f/2af/6d996f2af828cf712b64976d32c90432.png)
Да, теперь работает нормально. Вот только код стал, мягко говоря, немаленьким
html, body {
height: 100%;
padding: 0px;
margin: 0px;
}
.root {
width: 100%;
height: 100%;
background-color: yellow;
display: flex;
flex-direction: column
}
.toolbar1 {
background-color: green;
}
.main {
background-color: grey;
overflow: auto;
flex: 1;
}
.main-big-content {
background-color: black;
height: 2000px;
}
.toolbar2 {
background-color: cyan;
}
А теперь представьте что у вас внутри каждого блока есть свои блоки, и если не добавлять в каждый display: flex, flex-direction: column и flex: 1, все разъедется! Но давайте не извращаться и все сделаем по-нормальному:
html, body {
height: 100%;
padding: 0px;
margin: 0px;
}
.root {
height: 100%;
background-color: yellow;
display: grid;
grid-template-rows: min-content auto min-content
}
.toolbar1 {
background-color: green;
}
.main {
background-color: grey;
overflow: auto;
}
.main-big-content {
background-color: black;
height: 2000px;
}
.toolbar2 {
background-color: cyan;
}
![](https://habrastorage.org/getpro/habr/upload_files/2ef/131/cd5/2ef131cd56cd3bbb426603e27a943a95.png)
Все просто, понятно и без лишнего кода.
Я вас еще не убедил? Давайте усложним задачу. И внутри нашей структуры сделаем еще одну такую же структуру. Для начала воспользуемся flex-ом:
html, body {
height: 100%;
padding: 0px;
margin: 0px;
}
.root {
width: 100%;
height: 100%;
background-color: yellow;
display: flex;
flex-direction: column
}
.toolbar1 {
background-color: green;
}
.main {
background-color: grey;
overflow: auto;
flex: 1;
}
.main-big-content {
background-color: black;
height: 2000px;
}
.toolbar2 {
background-color: cyan;
}
</style>
<div class="root">
<div class="toolbar1">
<button>button1</button>
</div>
<div class="main">
<div class="main-2">
<div class="toolbar2-1">
<button>button2-1</button>
</div>
<div class="main-big-content">
</div>
<div class="toolbar2-2">
<button>button2-2</button>
</div>
</div>
</div>
<div class="toolbar2">
<button>button1</button>
</div>
</div>
Сверху и снизу мы хотим по две кнопки. Естественно, мы этого не получаем:
![](https://habrastorage.org/getpro/habr/upload_files/583/865/4de/5838654de066bec199298db65ead945d.png)
Придется опять писать кучу кода про флексы...
html, body {
height: 100%;
padding: 0px;
margin: 0px;
}
.root {
width: 100%;
height: 100%;
background-color: yellow;
display: flex;
flex-direction: column
}
.toolbar1, .toolbar2-1 {
background-color: green;
}
.main {
background-color: grey;
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
}
.main-2 {
background-color: grey;
overflow: auto;
flex: 1;
}
.main-big-content {
background-color: black;
height: 2000px;
}
.toolbar2, .toolbar2-2 {
background-color: cyan;
}
![](https://habrastorage.org/getpro/habr/upload_files/5c9/2f4/303/5c92f4303e05db3f231d7720d979f3e3.png)
Все работает. Но посмотрите какой ценой!
Давайте перепишем на grid:
html, body {
height: 100%;
padding: 0px;
margin: 0px;
}
.root {
width: 100%;
height: 100%;
background-color: yellow;
display: grid;
grid-template-rows: min-content auto min-content;
}
.toolbar1, .toolbar2-1 {
background-color: green;
}
.main {
background-color: grey;
display: grid;
grid-template-rows: min-content auto min-content;
overflow: hidden;
}
.main-2 {
background-color: grey;
overflow: auto;
}
.main-big-content {
background-color: black;
height: 2000px;
}
.toolbar2, .toolbar2-2 {
background-color: cyan;
}
Все намного проще! А результат такой же:
![](https://habrastorage.org/getpro/habr/upload_files/16b/d6d/e32/16bd6de3297f1f747ad4753c8af8c8d3.png)
А знаете в чем прикол? grid-template-rows на самом деле не нужны. Браузер умный, он сам справится:
html, body {
height: 100%;
padding: 0px;
margin: 0px;
}
.root {
width: 100%;
height: 100%;
background-color: yellow;
display: grid;
}
.toolbar1, .toolbar2-1 {
background-color: green;
}
.main {
background-color: grey;
display: grid;
overflow: hidden;
}
.main-2 {
background-color: grey;
overflow: auto;
}
.main-big-content {
background-color: black;
height: 2000px;
}
.toolbar2, .toolbar2-2 {
background-color: cyan;
}
![](https://habrastorage.org/getpro/habr/upload_files/c0c/03f/5ce/c0c03f5cece586f9b9912599ee137b4b.png)
Все равно все работает!
И да, вы конечно меня сейчас спросите: "А зачем тебе вложенные друг в друга grid-ы? Почему не обойтись одним?". И ответ: в данном случае можно обойтись. Но существуют ситуации, когда вы вынуждены использовать вложенные контейнеры, например, когда вы внутри виджета. Но давайте упростим код и обойдемся одним grid-ом:
<style>
html, body {
height: 100%;
padding: 0px;
margin: 0px;
}
.root {
width: 100%;
height: 100%;
background-color: yellow;
display: grid;
overflow: hidden;
}
.toolbar1, .toolbar2-1 {
background-color: green;
}
.main {
background-color: grey;
overflow: auto;
}
.main-big-content {
background-color: black;
height: 2000px;
}
.toolbar2, .toolbar2-2 {
background-color: cyan;
}
</style>
<div class="root">
<div class="toolbar1">
<button>button1</button>
</div>
<div class="toolbar2-1">
<button>button2-1</button>
</div>
<div class="main">
<div class="main-big-content">
</div>
</div>
<div class="toolbar2-2">
<button>button2-2</button>
</div>
<div class="toolbar2">
<button>button1</button>
</div>
</div>
![](https://habrastorage.org/getpro/habr/upload_files/03e/e9c/8bb/03ee9c8bb10e8c1524367a30f8a50a42.png)
Идеально. Начинайте использовать grid-ы!
odilovoybek
Вы поменяли несколько простых строк стилей, которые очень легки восприятию огромным однострочником. С использованием всяких CSS фреймворков намного легче использовать flexbox в этих примерах, надо было привести примеры с матричной разметкой и разметкой, где нужно, чтобы были разные размеры и тогда было бы понятно, что в некоторых сложных разметках лучше использовать grid, который уменьшает разброс стилей по разным селекторам/элементам.