Когда нужно использовать Flexbox

Очень интересная статья про то, когда всё-таки нужно использовать flexbox, а когда grid. Всё с примерами и объяснениями. В общем, как надо. Эта статья интересна именно тем, что появляется в переходный момент, когда существуют старые добрые флоаты, flexbox и grid. И все они уже довольно хорошо поддерживаются современными браузерами.

Адаптивный перевод статьи Use Cases For Flexbox 
Автор: Rachel Andrew. 
Кстати, очень советую почитать её книги и статьи.

Также советую почитать. Решающая CSS битва: Grid против Flexbox

И Вёрстка на Flexbox в CSS. Полный справочник (там же вы найдете детальное объяснение того, как работают замысловатые flex-grow и flex-shrink)

Так что использовать, Grid или Flexbox?

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

А если вы только пришли к этому вопросу, то вам стоит помнить, что CSS Grid и Flexbox оба являются частью CSS. Указывая display: grid или display: flex, вы зачастую применяете больше того, чего у них общего, нежели их различия. Grid и Flexbox используют свойства, которые входят в спецификацию Box Alignment (Модуль выравнивания в CSS), оба они основаны на концепциях, описанных в CSS Intrinsic & Extrinsic Sizing (Формирование свойственных и внешних, зависимых от них, размеров элементов).

Так что задавая вопрос, что использовать Grid или Flexbox, вы отчасти спрашиваете что-то типа, что должно быть в моём дизайне font-size или color? Скорее всего вам надо использовать оба, если потребуется. И уже точно тут никто не будет укорять вас в том, что вы выбрали неверный метод.

Мы не выбираем между Vue.js и React, Bootstrap или Foundation. Мы просто используем CSS, чтобы сверстать шаблон и нам нужно использовать его составляющие, которые будут иметь смысл при применении их в конкретной части нашего дизайна. Рассмотрите каждый компонент и решите, что и где лучше использовать или какие комбинации будут более подходящими.

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

Так для чего на самом деле нужен Flexbox?

Вот, как описывается flexbox в своей спецификации:

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

Я думаю, что ключевая фраза тут “распределение места и выравнивание контента”. Flexbox по своей сути берёт несколько элементов разных размеров и умещает их в контейнер, у которого сам по себе варьирующийся размер. Flexbox же ‘неженка’. Он пытается создать лучший шаблон из возможных для наших элементов, давая самым большим из них места побольше, а тем кто поменьше — места поменьше, соответственно, при этом стоя на страже читабельности всего контента.

Иногда люди находят flexbox сложным и странным. Зачастую так бывает, потому что люди пытаются использовать его как систему сеток — стараясь вернуть контроль над формированием размера и распределением места. Естественно, когда вы так делаете, flexbox может казаться странным и тяжёлым для понимания, потому что попросту вы боретесь с тем, что flexbox делает flexbox’ом, а именно с его гибкостью.

Следовательно, шаблоны подходящие для flex-разметки, это те, в которых нет нужды в pixel-perfect размерах для каждого элемента. Нам просто надо хорошо отобразить каждый рядом друг с другом.

Также, есть моменты, где вам понадобится “охватить” строки, однако при этом нет нужды в строгой сетке. Если мы возьмём примеры на grid’ах и flexbox, в которых будем использовать синтаксис авто заполнения грида и затем flex-контейнер с обернутыми flex-строками. То мы сразу увидим разницу между этими двумя методами.

В гриде, элементы выстроятся по строкам и колонкам. В то время, как количество колонок изменяется в зависимости от места, элементы всегда идут в следующую доступную грид-ячейку. По факту, нет способа указывать грид-элементу продолжительность треков, если в таком auto-flow сценарии есть пустые ячейки для заполнения.

А вот в flex-примере, последние элементы берут любое пространство, которое остаётся между ними; в этому случае у нас нет горизонтального или вертикального выравнивания.

Если у нас выствлен flex-basis на auto и какой-либо из flex-элементов больше, им также будет распределено больше места, так что выравнивание может быть довольно разным от строки к строке.

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

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

Возможно, в будущем мы сможем это делать без добавления контейнеру display: flex. Ну а сейчас, это скорее необходимость, чем данность, хотя эта лишняя строчка в CSS совсем не проблема.

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

Вы также можете выбрать Flexbox в ситуациях, где вам нужно держать контент в “подвале” контейнера, вместо того, чтобы он скакал туда-сюда по компоненту. В примере ниже, flex-контейнер показывает контент, как колонку, растягивая середину, которая выталкивает футер вниз компонента.

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

Я считаю, уж что flexbox делает хорошо, так это справляется с ситуациями, когда нужно добавить несколько дополнительных элементов, которые изначально не предполагались в дизайне. Для примера, если бы у меня был компонент навигации, использующий Grid, то нужно было бы достаточно треков для всех элементов, так как мне бы не хотелось, чтобы новая строка создалась в случае, когда у меня было бы “слишком много” элементов. А вот в Flexbox, пока я позволяю элементам быть “гибкими” от flex-basis 0 (или auto), то элементы бы допускали добавление других, новых элементов в строку, предоставляя им пространство.

Когда мне НЕ использовать Flexbox?

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

Пример на гридах сделан двухмерно. В общем это одновременно шаблон на строках и колонках. А вот пример на Flexbox сделан одномерно. Мы обернули флекс-строки, но распределение места происходит на построчной основе. Каждая строка обязательно ведёт себя как новый флекс-контейнер по-указанному flex-direction.

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

Ещё один момент, при котором Grid можно рассматривать, как лучшее решение, это когда вы применяете ширину или flex-basis как единицу длины для флекс-элементов, для того, чтобы выстроить их с другой строкой флекс-элементов или просто каким-нибудь образом ограничить “гибкость” (флексбоксность). Зачастую это говорит о том, что вам либо нужен двумерный шаблон или то, что управление через грид контейнер лучше подходит для этого случая.

Для примера, мы могли бы наш флекс-шаблон сделать похожим на гридовый , ограничив “флексбоксноть” (лучше этот термин, потому что он указывает на гибкость и растягиваемость элементов в flexbox) элементов. Выставляя flex-grow на 0 и указывая размер элементов в процентах — похожим образом мы бы могли выставлять размеры в потоковом гриде. В общем, если вы поняли, что если вы так делаете, то вам стоит рассмотреть способ на гридах, как более удачный подход, созданный именно для такого типа шаблонов.

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