Решающая CSS битва: Grid против Flexbox

Узнайте, чем они отличаются и когда их нужно использовать вместе.

Перевод: The ultimate CSS battle: Grid vs Flexbox Автор: Per Harald Borgen

CSS Flexbox стал крайне популярным среди Front-end разработчиков за последние несколько лет. И это не удивительно, поскольку теперь стало легче создавать динамические шаблоны и выравнивать контент внутри контейнеров.

Однако, на районе появился новый парниша по имени CSS Grid и у него очень много тех же возможностей, что и у Flexbox. В одних случаях, он даже лучше, чем Flexbox, в то время как в других совершенно нет.

Такой расклад событий вводит разработчиков в смятение. Поэтому, в этой статье мы сравним два модуля, как на микро, так и на макро уровнях.

Одномерное против двумерного

Если вы хотите получить урок из этой статьи, то пусть он пусть он будет таким. Flexbox это одномерные макеты, а Grid это двумерные.

Это означает, что если вы раскладываете объекты в одном направлении, к примеру, кнопку в header, то вам нужно применять Flexbox.

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

Однако, если вы собираетесь создать целый макет в двух измерениях, как с row, так и с column — то вам нужно использовать CSS Grid.

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

Теперь вы конечно же можете комбинировать оба метода. В примере выше, было бы идеально использовать Grid для всего макета, а затем Flexbox для выравнивания контента внутри header. Таким образом вы воспользуетесь лучшим от двух «взглядов на мир». 
В общем, ближе к концу статьи вы увидите, как именно это сделать .

Упор на контент или на макет?

Ещё одно кардинальное отличие в том, что Flexbox берет за основу контент, в то время как в основе Grid лежит сам макет и его общая разметка. С первых слов это всё довольно абстрактно, поэтому давайте взглянем на конкретный пример, который позволит нам легче понять суть того, что происходит.

Мы будем использовать header из предыдущего параграфа. Вот как выглядит его HTML.

<header>
<div>Home</div>
<div>Search</div>
<div>Logout</div>
</header>

Перед тем как мы зафлексбоксим макет, эти дивы будут располагаться друг над другом. Как тут:

Flexbox header

Итак, когда мы укажем display: flex все элементы аккуратненько встанут в линию.

header {
display: flex;
}

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

header > div:nth-child(3) {
margin-left: auto;
}

Это даст нам такой результат:

Что нужно тут знать, так это то, что мы дали элементам самим решить как им расположиться. Изначально не предопределялось ничего, кроме display: flex.

Это основное различие между Flexbox и Grid и сейчас это станет ещё понятнее, после того как мы переделаем header на Grid’ах.

Пусть даже CSS Grid не задуман для создания одномерных header’ов, это всё же хороший пример для проработки в этой статье, так как он научит понимать основные понятия между Flexbox и Grid.

Grid header

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

header {
display: grid;
grid-template-columns: repeat(10, 1fr);
}

Это будет идентично решению через Flexbox.

Но давайте взглянем поглубже и посмотрим в чем же разница. Зайдем в Chrome inspector, чтобы увидеть границы колонок.

Ключевое различие тут в том, что мы должны сначала выставить определения колонок макета. Начиная с определения ширины колонок и потом выставляя контент в доступные ячейки grid.

Этот подход заставил нас четко определить позицию, на сколько колонок мы хотим разделить header.

Пока мы не изменим сетку, выходит, что мы застряли с этими десятью колонками. Это ограничение, с которым бы мы не столкнулись, имея дело только с Flexbox.

Для того, чтобы кнопку logout поставить в конец секции справа, мы поставим этот элемент DOM в десятую колонку, как тут:

header > div:nth-child(3) {
grid-column: 10;
}

Вот как это будет выглядеть при детальном виде расположения колонок.

Мы не могли просто задать этому элементу margin-left: auto;, потому что кнопка logout уже была помещена в конкретную ячейку макета, а именно в третью колонку. И чтобы сдвинуть её, нам нужно найти ещё одну ячейку.

Совмещаем два подхода

А теперь давайте посмотрим, как применять два эти подхода вместе, объединяя header со всем нашим макетом. Мы начнем с построения самого макета.

Вот разметка:

<div class="container">
<header>HEADER</header>
<aside>MENU</aside>
<main>CONTENT</main>
<footer>FOOTER</footer>
</div>

Вот CSS:

.container {
display: grid;
grid-template-columns: repeat(12, 1fr);
grid-template-rows: 50px 350px 50px;
}

Вот так мы расставим элементы по сетке:

header {
grid-column: span 12;
}
aside {
grid-column: span 2;
}
main {
grid-column: span 10;
}
footer {
grid-column: span 12;
}

Теперь мы просто добавим header. Его мы зафлексбоксим, хотя он уже является элементом нашего Grid CSS.

header {
display: flex;
}

Теперь мы можем установить кнопку logout справа.

header > div:nth-child(3) {
margin-left: auto;
}

И теперь, у нас идеальный макет, который использует как Grid, так и Flexbox. Вот как выглядят оба контейнера.

Итак, теперь у вас имеется четкое понимание основ и конкретных различий между Flexbox и Grid, и самое важное — это понимание того, как использовать их вместе.

Поддержка браузеров

Перед тем как мы закончим, также надо упомянуть о поддержке браузерами. На момент написания этой статьи, 77% глобального трафика сайтов поддерживали CSS Grid и этот показатель постоянно растет.

Скорее всего, 2018 будет годом CSS Grid. Это будет его прорывом и он станет необходимым навыком для front-end разработчика. Точно также как это было с CSS Flexbox несколько лет назад.