Что лучше флексы или гриды
Решающая CSS битва: Grid против Flexbox
Узнайте, чем они отличаются и когда их нужно использовать вместе.
Dec 21, 2017 · 5 min read
👉 Мой Твиттер — там много из мира фронтенда, да и вообще поговорим🖖. Подписывайтесь, будет интересно: ) ✈️
CSS Flexbox стал крайне популярным среди Front-end разработчиков за последние несколько лет. И это не удивительно, поскольку теперь стало легче создавать динамические шаблоны и выравнивать контент внутри контейнеров.
Однако, на районе появился новый парниша по имени CSS Grid и у него очень много тех же возможностей, что и у Flexbox. В одних случаях, он даже лучше, чем Flexbox, в то время как в других совершенно нет.
Такой расклад событий вводит разработчиков в смятение. Поэтому, в этой статье мы сравним два модуля, как на микро, так и на макро уровнях.
Одномерное против двумерного
Если вы хотите получить урок из этой статьи, то пусть он пусть он будет таким. Flexbox это одномерные макеты, а Grid это двумерные.
Это означает, что если вы раскладываете объекты в одном направлении, к примеру, кнопку в header, то вам нужно применять Flexbox.
Это даст вам больше гибкости, чем в случе с CSS Grid. Также с этим будет проще работать в дальнейшем, а самое важное вы избежите лишней писанины.
В этом случае с CSS Grid вы получите больше гибкости, да и ваша разметка будет проще, а код станет понятнее для дальнейшей работы.
Упор на контент или на макет?
Ещё одно кардинальное отличие в том, что Flexbox берет за основу контент, в то время как в основе Grid лежит сам макет и его общая разметка. С первых слов это всё довольно абстрактно, поэтому давайте взглянем на конкретный пример, который позволит нам легче понять суть того, что происходит.
Мы будем использовать header из предыдущего параграфа. Вот как выглядит его HTML.
Перед тем как мы зафлексбоксим макет, эти дивы будут располагаться друг над другом. Как тут:
Flexbox header
Итак, когда мы укажем display: flex все элементы аккуратненько встанут в линию.
Для того, чтобы отправить кнопку logout в правый угол, мы просто укажем нужный элемент и зададим ему внешний отступ.
Это даст нам такой результат:
Это основное различие между Flexbox и Grid и сейчас это станет ещё понятнее, после того как мы переделаем header на Grid’ах.
Пусть даже CSS Grid не задуман для создания одномерных header’ов, это всё же хороший пример для проработки в этой статье, так как он научит понимать основные понятия между Flexbox и Grid.
Grid header
Мы можем создать наш header несколькими разными способами с помощью CSS Grid. Тут же мы увидим довольно понятный способ, где у grid есть десять колонок, каждая из которых является частью формирования ширины элемента.
Это будет идентично решению через Flexbox.
Но давайте взглянем поглубже и посмотрим в чем же разница. Зайдем в Chrome inspector, чтобы увидеть границы колонок.
Ключевое различие тут в том, что мы должны сначала выставить определения колонок макета. Начиная с определения ширины колонок и потом выставляя контент в доступные ячейки grid.
Этот подход заставил нас четко определить позицию, на сколько колонок мы хотим разделить header.
Пока мы не изменим сетку, выходит, что мы застряли с этими десятью колонками. Это ограничение, с которым бы мы не столкнулись, имея дело только с Flexbox.
Для того, чтобы кнопку logout поставить в конец секции справа, мы поставим этот элемент DOM в десятую колонку, как тут:
Вот как это будет выглядеть при детальном виде расположения колонок.
Совмещаем два подхода
А теперь давайте посмотрим, как применять два эти подхода вместе, объединяя header со всем нашим макетом. Мы начнем с построения самого макета.
Вот так мы расставим элементы по сетке:
Теперь мы просто добавим header. Его мы зафлексбоксим, хотя он уже является элементом нашего Grid CSS.
Теперь мы можем установить кнопку logout справа.
И теперь, у нас идеальный макет, который использует как Grid, так и Flexbox. Вот как выглядят оба контейнера.
Итак, теперь у вас имеется четкое понимание основ и конкретных различий между Flexbox и Grid, и самое важное — это понимание того, как использовать их вместе.
Поддержка браузеров
Перед тем как мы закончим, также надо упомянуть о поддержке браузерами. На момент написания этой статьи, 77% глобального трафика сайтов поддерживали CSS Grid и этот показатель постоянно растет.
Скорее всего, 2018 будет годом CSS Grid. Это будет его прорывом и он станет необходимым навыком для front-end разработчика. Точно также как это было с CSS Flexbox несколько лет назад.
Когда использовать флексы, а когда гриды
Сеткой или раскладкой обычно называют взаимное расположение крупных визуальных блоков на странице.
Можно мысленно разделить макет на не пересекающиеся друг с другом прямоугольники. Сначала вы получите самые крупные области, потом эти крупные области можно разделить на области поменьше, и так далее до мельчайших прямоугольников, которые выделяют отдельные слова или элементы страницы. Вся страница будет выглядеть как набор вложенных в друг друга прямоугольников, от самых крупных до самых мелких.
Сетка страницы от крупных до мелких прямоугольников
История
Не все верстальщики учились строить сетки веб-интерфейсов сразу на гридах. Некоторые начали верстать тогда, когда специальных инструментов для построения сеток ещё не было и приходилось использовать таблицы или флоаты, хотя их придумали для изъятия элементов из потока. Но когда в 2006 году появилась технология, предназначенная именно для построения сеток, — CSS Flex Layout (флексы) — таблицы и флоаты с этой целью постепенно перестали применять.
На тот момент выбор верстальщиков в пользу флексов был очевиден. Но с появлением в 2011 году ещё одного инструмента — CSS Grid Layout (гридов) — развернулся спор, который до сих пор продолжается. Верстальщики разделились на две категории: одни — за флексы, вторые — за гриды. И те, и другие пытаются обосновать свою позицию и убедить коллег в том, что правы именно они.
Сходства и различия
Масло в огонь подливает то, что гридами и флексами можно решать одни и те же задачи. Например, сделать стики-футер (когда подвал сайта прилипает к нижней части экрана), случайное количество карточек товара или каркас всей страницы.
Одно из преимуществ гридов — зазоры между линиями (gap), но и они перешли уже в общую спецификацию. Теперь gap можно использовать во флексах, что ещё больше добавляет путаницу в выборе CSS-свойства.
Но тем не менее между флексами и гридами есть значимые различия.
Флексы — одномерные. Это значит, что управлять расположением в рядах нельзя.
Пример сетки на флексах
Гриды же двухмерные. То есть можно передвигать элементы между строками и рядами.
Пример сетки на гридах
Например, если верстальщик хочет расположить логотип, навигацию и номер телефона в шапке, то проще будет использовать флексы. Именно проще: гриды тоже могут решить эту задачу, но флексы справятся с ней гораздо быстрее.
Если взять целый сайт, с шапкой, контентной частью и подвалом, то здесь речь будет идти уже о двухмерности интерфейса. И хотя флексами сайт тоже можно сверстать, гриды сделают это эффективнее и надёжнее.
Таким образом, гриды в основном используются для построения сетки всего интерфейса. Флексы же — для расположения элементов внутри сетки.
Гриды — для каркаса сайта, флексы — для контента.
Мы рекомендуем придерживаться именно такого порядка. А по мере работы с этими двумя свойствами вы и сами начнёте чувствовать, в каких случаях та или иная технология подходит больше.
Чтобы быстрее это понять, можно потренироваться на навыках «Построение сеток на флексах» и «Построение сеток на гридах». Навыки покажут все различия между способами построения сеток, помогут отработать оба и уложить это в голове.
CSS Grid и Flexbox: сравнение на практике
Ещё недавно макет для всех страниц HTML верстался с помощью таблиц, float и других свойств CSS, которые не очень хорошо подходят для стилизации сложных веб-страниц.
Затем появился Flexbox — режим вёрстки, который был специально разработан для создания надёжных адаптивных страниц. Flexbox упростил правильное выравнивание элементов и их содержимого и теперь является предпочтительной системой CSS для большинства веб-разработчиков.
Но теперь у нас есть новый претендент на титул за звание «лучшей системы для вёрстки макетов HTML» (название титула ещё в процессе разработки»). Это CSS Grid и в ближайшее время эта система будет доступна в браузерах Firefox 52 и Chrome 57, а вскоре, как я надеюсь, и в других браузерах.
Базовый макет
Чтобы понять, каково это — создавать макеты на каждой системе, мы сделаем одну и ту же HTML-страницу дважды — один раз с помощью Flexbox, а затем на CSS Grid. Вы можете скачать оба проекта отсюда или проверить их в этой демонстрационной версии.
Уменьшенный макет веб-страницы
Дизайн довольно простой — он состоит из выровненного по центру контейнера, внутри которого у нас есть шапка, основной раздел, боковая панель и подвал. Вот главные «испытания», которые мы должны провести, сохраняя CSS и HTML по возможности чистыми:
Как вы можете видеть, ради сравнения мы оставили всё максимально простым. Начнём с первого испытания.
Испытание 1. Размещение разделов страницы
Решение на Flexbox
Добавляем display: flex к контейнеру и задаём направление дочерних элементов по вертикали. Это позиционирует все разделы друг под другом.
Теперь нам нужно сделать так, чтобы основной раздел и боковая панель располагались рядом. Поскольку flex-контейнеры обычно однонаправлены, нам нужно добавить дополнительный элемент.
Затем мы устанавливаем этому элементу display: flex и flex-direction с противоположным направлением.
Последний шаг — задать размеры основного раздела и боковой панели. Мы хотим, чтобы основное содержимое было в три раза шире боковой панели, что несложно сделать с помощью flex или процентов.
Как вы можете видеть, Flexbox сделал всё хорошо, но нам кроме этого понадобилось довольно много свойств CSS плюс дополнительный элемент HTML. Давайте посмотрим, как будет работать CSS Grid.
Решение на CSS Grid
Теперь мы можем настроить нашу сетку и определить расположение каждой области. Вначале код может показаться довольно сложным, но как только вы познакомитесь с системой сетки, он становится проще для понимания.
Испытание 2. Делаем страницу адаптивной
Решение на Flexbox
Наша страница довольно простая, поэтому в медиа-запросе мало работы, но в более сложном макете придётся много чего переделывать.
Решение на CSS Grid
Или можем переопределить весь макет с нуля, если считаем, что это решение чище.
Испытание 3. Выравнивание компонентов шапки
Наша шапка включает некоторые ссылки навигации и кнопку. Мы хотим, чтобы навигация была слева, а кнопка справа. Ссылки внутри навигации должны быть выровнены относительно друг друга.
Решение на Flexbox
Мы уже делали похожий макет на Flexbox в одной из наших старых статей — Простейший способ создания адаптивной шапки. Техника довольно простая:
Только две строки! Совсем неплохо. Давайте посмотрим, как с этим справится CSS Grid.
Решение на CSS Grid
Чтобы разделить навигацию и кнопку, мы должны добавить display: grid к header и настроить двухколоночную сетку. Нам также понадобятся две дополнительные строки в CSS, чтобы позиционировать всё на соответствующих границах.
Что касается ссылок в одну строку внутри навигации, у нас не получилось сделать это корректно с CSS Grid. Вот как выглядит наша лучшая попытка:
Понятно, что CSS Grid не справилась с этой частью макета, но это и не удивительно — основное внимание уделяется выравниванию контейнеров, а не содержимому внутри них. Эта система не для нанесения последних штрихов.
Выводы
Если вы прочитали статью целиком (а это отличная работа!), выводы не должны вас удивить. На деле нет лучшей системы — и Flexbox и CSS Grid хороши по своему и должны использоваться совместно, а не как альтернатива друг другу.
Для тех из вас, кто перепрыгнул непосредственно к выводам этой статьи (не волнуйтесь, мы тоже так делаем), вот краткий итог сравнения:
Выбор CSS макета — Grid или Flexbox?
Удачно оформленный макет удерживает пользователей на сайте, так как делает важные элементы доступными и легко находимыми. Слабые же макеты отпугивают посетителей, которые покидают ресурс, так и не найдя того, за чем пришли.
В веб-дизайне макет – это то, как сайт отображается на экране. В HTML 5 есть довольно много элементов, определяющих внешний вид веб-страницы: заголовок, навигационный блок, абзац, сноска, статья и нижний колонтитул, каждый из которых имеет свое особое значение в создании макета. Вместе же они формируют четыре основных раздела страницы – заголовок/баннер, поисковый блок, содержимое и нижний колонтитул.
Языки программирования помогают сделать сайты «живыми», но в основе каждой страницы по-прежнему лежит старый добрый HTML. При рассмотрении макетов необходимо учитывать факторы, определяющие их качество, а именно отзывчивость, порты просмотра, устройства отображения, браузеры и размеры экранов пользователей. Грамотный макет не только здорово смотрится, но также может сохранять задуманную структуру, вписываясь в экраны с любым возможным соотношением сторон. Как раз за эту подстройку и отвечает CSS. В текущей статье мы в общих чертах рассмотрим два его мощнейших инструмента: Flexbox и Grid.
Что такое макет CSS FLEXBOX?
Flexbox – это общепринятое сокращение для Flexible Box Module (модуль гибкого контейнера), который представляет собой одномерную модель макета. Это значит, что одновременно он может работать только со строкой или столбцом, но не с обоими сразу. Flexbox эффективно справляется с выравниванием, распределением и направлением элементов страницы.
Двумя основными понятиями этой модели макета являются главная ось и поперечная ось. Главная ось flex-контейнера – это основное направление, вдоль которого выстраиваются flex-элементы, поперечная же ось ей перпендикулярна.
Для начала давайте обернем HTML-элементы div во flex-wrapper.
В CSS родительский контейнер “flex-wrapper” преобразуется во flexbox с помощью простой инструкции.
При добавлении элементов и свойств я буду использовать яркие цвета и отступы, чтобы выделить контейнеры и div-элементы.
Вы можете видеть, как удачно элементы div располагаются по горизонтали, но при этом они занимают не всю область контейнера, и в конце остается пустое пространство. Это можно исправить, добавив flex-grow.
Свойство flex-grow отвечает за распределение каждого элемента flex-контейнера. По умолчанию значение этого свойства равно 0, присваивая же разное количество единиц div-элементам, вы увеличиваете их по отношению к остальным. Противоположный эффект дает свойство flex-shrink.
FLEX-DIRECTION
Flex-direction определяет направление размещения элементов контейнера. С его помощью можно заставить их располагаться по направлению вверх, вниз, влево или вправо, а также в обратном порядке. По умолчанию элементы flex-контейнера упорядочены вдоль главной оси слева направо.
Здесь элементы также отображаются слева направо, но в обратном порядке. В итоге четвертый div становится первым, а первый, в свою очередь, последним.
Здесь же упорядочивание происходит уже вертикально – сверху вниз.
Теперь элементы также расположены вертикально, но в обратном порядке, т.е. четвертый оказался вверху, а первый внизу.
FLEX BASIS
Flex basis определяет размер элемента внутри контейнера. При этом значение размера может указываться в em, px или процентах. Это свойство отличается от flex-grow тем, что не распределяет пространство между элементами контейнера равномерно.
Flex – это сокращенное свойство, объединяющее flex-shrink, flex-grow и flex-basis. Его рекомендуется использовать вместо раздельного написания свойств, указывая в нем их значения в следующем порядке: flex-grow, flex-shrink, flex-basis.
JUSTIFY-CONTENT И ALIGN-SELF
Justify-content и align-self – это идеальное решение для размещения div или контейнера в центре окна браузера.
CSS GRID Layout
CSS grid (сетка) представляет собой мощный двухмерный макет, при использовании которого можно одновременно работать со строками и столбцами. В основе CSS Grid лежит неявное разделение экрана на сетку из 12 частей, в которые в итоге и вписываются элементы.
Преимущество этой технологии перед Flexbox и другими видами макетов в ее возможности работать двухмерно. При этом она также упрощает позиционирование, и элементы контейнера могут размещаться, перекрывая друг на друга.
ОПРЕДЕЛЕНИЕ СЕТКИ В CSS GRID
Преобразование HTML-структуры в СSS сетку выполняется одной простой CSS инструкцией.
GRID TEMPLATE-COLUMNS И GRID-TEMPLATE-ROWS
Свойства grid-template-columns и grid-template-row устанавливают величину столбца или строки, определяя размер div-элементов согласно присвоенным значениям, которые указываются в px, fr, процентах или em.
grid-template-columns: 40px 1fr 20%; — эта строка дает браузеру команду присвоить первому div ширину 40px, второй же занимает одну долю отведенного места, а третий 20%. Элементы с 4 по 6 автоматически смещаются под первые 3 и принимают те же значения в том же порядке, т.е. div 4 получает размер 40px, div 5 — одну долю, а div 6 – 20%.
Чтобы поместить все шесть div-элементов в одну строку нужно указать в свойстве grid-template-column шесть значений. При этом не обязательно использовать для столбцов разные единицы измерения, можно задать только проценты, fr или px.
grid-template-rows: 200px; — эта строка присваивает всем div-элементам высоту в 200px.
Присвоив 16,7% для 6 точек, я успешно разделил шесть элементов контейнера по шести равным частям экрана. Значение 16,7% я выбрал, потому что при умножении 16,7 на 6 как раз получится 100% ширины экрана.
Использование процентов и пикселей работает идеально, но им недостает гибкости, и они уступают наиболее эффективному компоненту – долям CSS сетки.
Fr – это дробная единица, которая присваивает каждому элементу одну долю доступного пространства, которое можно увеличивать, выделяя под div необходимую ему область.
Теперь наше свойство grid-template-columns стало:
В результате каждый div-элемент был размещен на экране равномерно.
Изменив второе и четвертое значения, мы сделали соответствующие элементы вдвое больше остальных. Самое же главное, что они по-прежнему распределяются в браузере равномерно и имеют высокую отзывчивость.
ФУНКЦИЯ REPEAT
Вместо того, чтобы повторно переписывать значения, можно задействовать функцию repeat, которая позволит сделать это всего один раз.
Синтаксис этой функции относительно прост. Сначала пишем слово “repeat”, после которого определяем, сколько раз нужно повторить размер, в данном случае 6, а затем указываем величину единицы измерения. Эта функция аналогичным образом работает со свойством template-row и позволяет использовать как fr, em, px, так и проценты.
Gap – это отступ, представляющий свойство CSS сетки, которое позволяет указывать расстояние между div-элементами контейнера. Работает оно точно также, как свойство margin и измеряется обычно в px.
GRID-COLUMN-START/GRID-COLUMN-END И GRID-ROW-START/GRID-ROW-END
Свойства grid-column-start и grid-column-end помещают элемент сетки в конкретное место столбца относительно определенных строк сетки. Свойства же grid-row-start и grid-row-end делают то же самое, но в отношении строки. Присваивая этим свойствам значения, можно удобно управлять начальной и конечной точкой элемента сетки, выделяя ему нужную область.
Если вы присвоите указанные значения первому div, то заметите, что он смещает второй div на одну единицу и занимает первые две позиции, смещая третий div вниз. В отношении же строк теперь он занимает три позиции и становится выше.
В программировании индексация производится по особому правилу, согласно которому мы обычно начинаем отсчет с 0. В этом случае последнее значение, как правило, упоминается, но не учитывается. Например, значение свойства grid-column-end равно 3, но по факту оканчивается оно на 2-х также, как и grid-row-end оканчивается на 3-х, а не на 4-х.
GRID-COLUMNS И GRID-ROW
Это сокращенный вариант для свойств grid-column-start/grid-column-end и grid-row-start/grid-row-end. В качестве значений в этом случае через слэш указываются начальные и конечные позиции элемента:
СОЗДАНИЕ ГАЛЕРЕЙ
CSS сетка идеально подходит для создания галерей. С помощью небольшого количества кода и манипуляций вы можете создать их прекрасные отзывчивые макеты.
Мозаичный макет галереи
Такой макет создает равные плитки изображений, равномерно распределенные по странице/контейнеру.
Этот код создаст прекрасный макет плиточной галереи изображений.
Макет Masonry-галереи
Этот макет уже неравномерен, так как не имеет фиксированной высоты строк. Однако при помощи grid-columns и grid-rows мы можем подстраивать изображения, чтобы они вписывались в назначенные дробные единицы и перемещались по ним нужным нам образом.
GRID TEMPLATE AREAS
Свойство Grid-template-areas присваивает элементам имена, чтобы свойство grid-area могло на них ссылаться. Работает оно аналогично grid-column и grid-row, позволяя легко отображать и размещать конкретные области в структуре сетки.
GRID AREAS
Ссылаться на именованные области необходимо в порядке их вызова. Например, область сетки для #one не может быть нижним колонтитулом, поскольку эта область сетки именуется последней. Нарушение же правильного порядка приведет к ошибке в дизайне.
Что же лучше — Flexbox или Grid?
В своей сути Grid является макетом на основе контейнеров, а Flexbox на основе содержимого. И тот, и другой по-своему эффективен, хотя CSS Grid включает больше возможностей и позволяет легче манипулировать строками и столбцами сетки. Прежде чем решать, какой использовать, следует проанализировать сложность, структуру и содержимое создаваемого вами сайта. Приведу еще одно несколько углубленное сравнение: в макете flexbox размер ячейки (flex-элемента) определяется в самом flex-элементе, а в макете Grid размер элемента определяется уже в его контейнере.
Лично я могу посоветовать использовать CSS Grid для общего макета сайта, а затем уже Flexbox для элементов контейнера. Однако CSS Grid также отлично работает с отдельными элементами и учитывает нюансы реальной структуры сетки лучше, чем Flexbox. Например, инструкция grid-template-areas отобразит структуру сайта буквально за несколько секунд, после чего вы сможете сосредоточится на выравнивании контента по своему усмотрению.