[Перевод] Grid или Flexbox?

Мишель Баркер, автор материала, перевод которого мы сегодня публикуем, говорит, что недавнее обсуждение в Twitter, начатое Крисом Койером, заставило её задуматься о том, как веб-разработчики делают выбор между технологиями CSS Grid Layout и CSS Flexbox Layout при разработке макетов.

4pat6zgwycemjrtkqydjivtjw7s.png

Крис Койер в своём твите задал аудитории вопрос о том, как те, кто знает о том, что такое Grid и Flexbox, предпочитают объяснять разницу между этими технологиями.

Среди ответов на этот вопрос, что, по словам Мишель, вполне ожидаемо, можно было отметить ценные идеи Рэйчел Эндрю и Джен Симмонс.
Рэйчел сказала, что технология Flexbox предназначена для разработки одномерных макетов, представляющих собой описание расположения элементов в строке или в столбце. А технология Grid предназначена для разработки двумерных макетов, в которые входят и строки, и столбцы.

Джен говорит, что, технология Grid используется для описания строк и столбцов макетов. При этом содержимое будет располагаться в ячейках макета именно так, как это нужно разработчику. При использовании Flexbox это не так, причём, речь идёт не только о размещении данных во втором измерении (это и так понятно), но и о размещении их в одном измерении. Технология Flexbox не подходит для большинства случаев, в которых её используют.

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

Читая ответы на вопрос Криса, Мишель была удивлена тем количеством людей, которые говорили о том, что они использовали бы Grid лишь для макетов уровня страницы, и Flexbox — для всего остального. Если вы тоже придерживаетесь подобного правила — это значит, что вы серьёзно ограничиваете себя в том, что касается использования мощных возможностей Grid в различных ситуациях. Главное, что автору материала хотелось бы порекомендовать веб-разработчикам, заключается в том, что каждый макет стоит воспринимать как нечто особенное, анализировать доступные возможности, и не делать предположений о том, какие технологии понадобятся для его создания. Вот некоторые вопросы, которые можно задать себе при выборе технологии, подходящей для разработки макета.

Много ли вычислений приходится выполнять?


Приведу тут мой ответ на вопрос Криса. Я сказала тогда, что если мне кажется, что при формировании макета приходится слишком часто пользоваться CSS-функцией calc(), то это обычно говорит о том, что мне нужна технология Grid, а не Flexbox.

Если вам приходится часто прибегать к функции calc() для точного расчёта размеров строк и столбцов (если нужно, например, принимать во внимание внутренние поля), то это нередко указывает на то, что вам стоит рассмотреть возможность использования технологии Grid, так как применение единицы измерения fr значительно упростит вам жизнь. Хотя, в качестве рекомендации общего характера, этот совет вполне жизнеспособен, он не описывает полной картины происходящего. Иногда Grid может понадобиться и в тех случаях, когда при построении макета функция calc() не используется. Например — в ситуации, когда речь идёт о двумерном макете с фиксированной шириной, элементы которого имеют 200 пикселей в ширину. При разработке такого макета для того чтобы узнать ширину элементов функция calc() не нужна, но при этом могут оказаться чрезвычайно полезными особенности поведения макетов, построенных на основе Grid. Аналогично, возможны и ситуации, в которых лучше всего воспользоваться Flexbox и при этом, неизбежно, применить функцию calc(). В результате то, о чём мы тут говорим, лучше всего воспринимать не как жёсткое правило, вроде такого: «Используете calc() и Flexbox? Значит вам необходимо переходить на Grid», а как информацию к размышлению.

Одно измерение или два?


Серьёзное различие технологий Grid и Flexbox заключается в том, что первая позволяет управлять расположением элементов в двух измерениях (в строках и столбцах), а вторая этого не позволяет. Опять же, это не означает, что никогда не следует использовать Grid для одномерных макетов. Я часто выбираю именно Grid — в тех случаях, когда мне нужна высокая точность в управлении размерами и положением элементов, расположенных в одном измерении. Данный подход продемонстрирован в этом примере на CodePen, и в этой сопутствующей ему статье.

703582bd98cbae699b2f5e1d4cdc2070.png


Пример использования Grid

Как должны вести себя элементы?


Технологию Grid часто имеет смысл использовать в тех случаях, когда разработчику нужен контроль над поведением макета в двух измерениях. Однако это не говорит о том, что Grid всегда лучше Flexbox. При использовании Grid в распоряжении разработчика имеются строки и столбцы, ячейки, и так называемые грид-области (grid area), представляющие собой одну ячейку или группу из нескольких ячеек. При использовании Grid элементы должны быть расположены в этих ячейках или областях.

Предположим, у нас имеется макет, основанный на Grid, отличающийся следующими особенностями: есть девять элементов, расположенных слева направо в трёх строках по три элемента, между элементами имеются промежутки (gap) размером в 20 пикселей. Такой макет можно создать как с использованием Grid, так и с использованием Flexbox. Код описания такого макета, основанного на Grid, оказывается гораздо проще и чище:

.grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-auto-rows: 200px;
    /* Исходим из предположения о том, что нам нужно, чтобы строки обладали бы фиксированной высотой. Тут можно остановиться и на значении по умолчанию, `auto`, если нужно, чтобы высота строк зависела бы от их содержимого. */
    gap: 20px;
}


Применение подобного макета приводит к тому, что элементы размещаются автоматически, нам при этом ничего больше делать не нужно. Если же мы дадим себе время на размышления, то мы можем использовать функции Grid auto-fit() и minmax(), что позволит нам получить полностью отзывчивый макет без применения медиа-запросов. Откройте этот пример, попробуйте поменять размер окна и посмотрите на то, что получится.

1ef71fe49f625c06bf7b198bb382803e.png


Пример использования Grid

Подробнее об этой технике, а также о некоторых других полезных вещах, можно узнать, посмотрев это видео.

Если бы мы создавали подобный макет с помощью Flexbox, то, в отличие от только что описанного примера, нам понадобилось бы стилизовать и элементы, и контейнер:

.grid {
    display: flex;
    flex-wrap: wrap;
    margin: -10px;
    width: calc(100% + 20px);
}

.item {
    width: calc((100% / 3) - 20px);
    flex: 0 0 auto;
    margin: 0 10px 20px 10px;
}


Тут, в контейнере, понадобится указывать отрицательное значение для свойства margin — для того чтобы нейтрализовать тот факт, что общая ширина элементов больше, чем сам контейнер, и таким образом осуществить перенос данных на следующую строку. Кроме того, этот пример не может продемонстрировать то же самое отзывчивое поведение без дополнительных усилий с нашей стороны. Далее, надо отметить, что здесь, вероятно, может потребоваться использование медиа-запросов.

Вот пример на CodePen, который иллюстрирует вышесказанное.

282a96466df7961518df4bb73c6c55eb.png


Пример использования Flexbox

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

Многие современные CSS-фреймворки используют некие вариации этого метода для представления макетов. И, кстати, если вы хотите пойти именно таким путём, то могу порекомендовать Susy, набор инструментов, который берёт на себя все сложности по созданию подобных макетов.

Итак, что же лучше выбрать в этой ситуации? Grid или Flexbox? Возникает такое ощущение, что у Grid тут имеются некоторые неоспоримые преимущества, но для того чтобы ответить на этот вопрос, нам надо подумать о том, что должно произойти в том случае, если у нас имеется более девяти, но менее 12 элементов (если их будет, например, 12, то это позволит им полностью заполнить новую строку). Нужно ли нам, чтобы новые элементы просто находились бы в начале следующей строки, как было в тех примерах, что мы уже видели? Или нам надо, чтобы они вели бы себя как-нибудь иначе? Возможно, если в очередной строке будет находиться лишь один элемент, то нам нужно, чтобы он занял бы всё пространство этой строки, как в варианте A следующего примера? Или, может быть, если в новой строке будет всего два элемента, нам нужно, чтобы они были бы выровнены по центру, как в примере B?

72fb20f15b4a8ac059bb9c27246caa0a.png


Разные варианты размещения элементов в последней строке

При использовании макета, основанного на Grid, с применением автоматического размещения элементов, в нашем распоряжении оказывается лишь один вариант — размещение нового элемента в доступной ячейке, расположенной слева. Подобное размещение элементов можно встретить в предыдущих примерах. Тут мы исходим из предположения о том, что свойство direction не установлено в значение rtl (в таком случае элементы располагались бы справа налево, и единственный элемент в последней строке располагался бы в правой ячейке). В результате новые элементы при использовании Grid размещаются в следующих доступных ячейках сетки. Технология Flexbox позволяет гибко управлять расположением элементов. Это означает, что мы можем управлять поведением элементов, используя комбинацию свойств, управляющих размещением элементов и их выравниванием.

Вот пример, в котором продемонстрированы такие макеты, при использовании которых один или два элемента, приходящиеся на строку, рассчитанную на три элемента, занимают всю эту строку.

be084a26e7d960d38eb87f972bf32ae3.png


Элемент занимает всё доступное пространство строки

В результате оказывается, что независимо от технологии, используемой для формирования макета, всё сводится к тому, какое именно поведение элементов, расположенных в макете, интересует разработчика. И в разных ситуациях на один и тот же вопрос могут быть даны различные ответы.

Пытаетесь ли вы заменить Flexbox на Grid?


Когда я выступаю на различных мероприятиях, меня нередко спрашивают о том, когда я использовала бы Flexbox вместо Grid, и о том, нужна ли нам вообще такая технология, как Flexbox. Как мы уже видели в предыдущем примере, Grid — это не замена Flexbox. Обе технологии довольно-таки мирно сосуществуют, и знание о том, в каких ситуациях каждая из них лучше всего показывает себя, расширяет возможности по проектированию макетов.

29262a312aa36de45ed105193efbf936.jpg


Пример компонента

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

1fe1380366abe525f1dba84c82275f56.png


Меню, созданное средствами Flexbox

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

Как макет должен выглядеть в браузерах, которые не поддерживают технологию Grid?


Если мы пользуемся технологией Grid, то одной из возможных проблем, которую нам нужно принимать во внимание, является поддержка этой технологии браузерами. Тут же нам нужно продумать и то, что будет происходить в том случае, если наша страница будет выводиться в одном из браузеров, не поддерживающих Grid (например — в IE 11 и ниже). Мой подход к решению этой проблемы заключается в использовании правил @supports и в подготовке кода, предназначенного для разных браузеров. Часто (но не всегда) я, в качестве замены макета, основанного на Grid, использую макет, основанный на Flexbox, предназначенный для достаточно старых браузеров.

.grid {
    display: flex;
    flex-wrap: wrap;
    /* Продолжение кода, предназначенного для старых браузеров */
}

@supports (display: grid) {
    .grid {
        display: grid;
        /* Продолжение кода, использующего Grid */
    }
}


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

Итоги


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

Уважаемые читатели! В каких ситуациях вы пользуетесь технологией Grid, а в каких — Flexbox?

1ba550d25e8846ce8805de564da6aa63.png

© Habrahabr.ru