Flexbox: насколько велика эта гибкая коробка?

Продолжаю публикацию переводов по особенностям CSS-технологии Flexbox.


Из цикла опубликованы следующие статьи:

  1. Что происходит при создании контейнера Flexbox.
  2. Все, что вам нужно знать о выравнивании во Flexbox.


Краткое резюме

В последних двух статьях мы рассмотрели, что происходит при создании flex-контейнера, а также рассмотрели выравнивание. На этот раз мы рассмотрим часто запутанную проблему размеров во Flexbox. Как Flexbox решает, насколько большие должны быть элементы?

Это третья часть моей серии о Flexbox. В последних двух статьях мы рассмотрели, что происходит при создании flex-контейнера, и исследовали выравнивание, как оно работает во Flexbox. На этот раз мы собираемся взглянуть на размеры. Как мы контролируем размер наших flex элементов, и какой выбор делает браузер, когда он регулирует размер?

Исходное отображение Flex элементов

Если у меня есть набор элементов, которые имеют переменную длину внутреннего содержимого, и установить их родителю display: flex, элементы будут отображаться в виде строки и выстраиваться с начала координатной оси. В приведенном ниже примере мои три элемента имеют небольшой размер содержимого и могут отображать содержимое каждого элемента в виде непрерывной строки. В конце flex контейнера есть пространство, в которое элементы не растут, потому что начальное значение flex-grow равно 0, без растягивания.

Элементы flex имеют место для отображения в одной строке
Рис_1. Элементы flex имеют место для отображения в одной строке

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

Пространство распределяется, чтобы дать больше места для более длинного элемента
Рис_2. Пространство распределяется, чтобы дать больше места для более длинного элемента

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

CSS спецификация расчета внутренних и внешних размеров (CSS Intrinsic And Extrinsic Sizing)

Глядя на что—либо о расчете размеров в спецификации Flexbox, Вы довольно быстро обнаружите, что большая часть необходимой вам информации находится в другой спецификации — CSS Intrisnic and Extrinsic Sizing. Это потому, что концепция расчета размеров, которые мы используем, не уникальна для Flexbox, также как и свойства выравнивания не являются уникальными для Flexbox.

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

Предпочтительный размер (preferred size)

Предпочтительный размер элемента это размер, определяемый шириной или высотой, или логическими псевдонимами этих свойств среди inline-size и block-size. Воспользовавшись:

.box {     width: 500px; }

или логическим псевдонимом inline-size:

.box {     inline-size: 500px; }

вы заявляете, что хотите, чтобы ваш блок был шириной 500 пикселей или 500 пикселей в ряд.

Минимальный размер содержимого (MIN-CONTENT SIZE)

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

Размер максимального содержимого (MAX-CONTENT SIZE)

Максимальный размер содержимого-это наибольший размер элемента, в котором может содержаться содержимое. Если элемент содержит текст без форматирования, то он будет отображаться в виде одной длинной непрерывной строки.

Основной размер гибкого элемента (FLEX ITEM MAIN SIZE)

Основной размер гибкого элемента это его размер в главном направлении. Если вы работаете в строке на английском языке, то основным размером является ширина. В столбце на английском языке основным размером является высота.

Элементы также имеют минимальный и максимальный размер определяемый как min-width или min-height в главном направлении.

Проработка размера flex-элемента

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

  • flex-grow: 0;
  • flex-shrink: 1;
  • flex-basis: auto.

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

В тоже время, если flex-basis является auto а flex-grow: 1, распределяется только свободное пространство, учитывая размер контента.

В ситуации, когда нет свободного места, например, когда у нас больше контента, чем может поместиться в одной строке, тогда нет пространства для распределения.

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

Определение авто (defining auto)

Когда auto определяется как значение для чего-нибудь в CSS, оно должно иметь очень точное значение в том же контексте, на которое стоит взглянуть. Рабочая группа CSS тратит много времени на выяснение того, что означает auto в любом контексте, как объясняет этот разговор с редактором спецификаций Fantasai.

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

При указании во flex-элементе ключевое слово auto возвращает значение свойства main size в качестве используемого «flex-basis«. Если это значение само по себе auto, то используется значение content.

Таким образом, если наш flex-basisauto, Flexbox смотрит на определение свойства main size. Мы имели бы main size, если мы дали одному из наших flex элементов ширину. В примере ниже, все предметы имеют ширину 110px, поэтому это значение используется в качестве main size т.к. flex-basis — авто.

Однако в нашем первоначальном примере есть элементы, у которых нет ширины, это означает, что их main sizeauto, и поэтому нам нужно перейти к следующему высказыванию: “если это значение само по себе auto, то используется значение content.”

Теперь нам нужно посмотреть, что говорит спецификация о ключевом слове content. Это еще одно значение, которое вы можете использовать (в поддерживающих браузерах) для вашего flex-basis, например:

.item {     flex: 1 1 content; }

Спецификация определяет content следующим образом:

Указывает на автоматический размер, основываясь на содержимом flex-элемента. (Обычно он эквивалентен размеру max-content, но с настройками для обработки пропорций формата, внутренних ограничений размера и ортогональных потоков.

В нашем примере с flex-элементами, содержащими текст, мы можем игнорировать некоторые более сложные настройки и рассматривать содержимое как размер max-content.

Это объясняет, почему, когда у нас есть небольшое количество текста в каждом элементе, текст не переносится. flex-элементы имеют автоматический размер, поэтому Flexbox просматривает их размер max-content, элементы помещаются в контейнер такого размера, и работа выполнена!

На этом история не заканчивается, так как когда мы добавляем еще контент, элементы не остаются в размере max-content. Если бы они это делали, то вырвались бы из flex-контейнера и вызвали бы переполнение. Как только они заполнят контейнер, содержимое начинает переноситься, и элементы становятся разных размеров, основываясь на содержимом внутри них.

Разрешение гибких длин

Именно в этот момент спецификация становится достаточно сложной, однако шаги, которые нужно пройти, заключаются в следующем:

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

Если размер контейнера больше чем итог, то мы будем заботиться о flex-grow факторе, так как у нас есть место для роста.

В первом случае наши элементы имеют доступное пространство для роста
Рис_3. В первом случае наши элементы имеют доступное пространство для роста.

Если размер контейнера меньше итога, то мы будем заботиться о коэффициенте flex-shrink, поскольку нам нужно сокращаться.

Во втором случае наши элементы слишком большие и требуют сжатия, чтобы вписаться в контейнер
Рис_4. Во втором случае наши элементы слишком большие и требуют сжатия, чтобы вписаться в контейнер.

Заморозьте любые негибкие элементы, что означает, что мы уже можем принять решение о размере для некоторых элементов. Если мы используем flex-grow это будет включать в себя все элементы, которые имеют flex-grow: 0. Это сценарий, который мы имеем, когда наши flex элементы имеют свободное пространство в контейнере. Начальное значение flex-grow равно 0, поэтому они становятся такими же большими, как их максимальная ширина, а затем они больше не растут от основного размера.

Если мы используем flex-shrink, то это будет включать в себя все элементы с flex-shrink: 0. Мы можем увидеть, что происходит на этом шаге, если мы дадим нашему набору flex элементов flex-shrink: 0. Элементы становятся замороженными в состоянии max-content и поэтому не сгибаются и не укладываются в контейнер.

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

Фактор flex-shrink умножается на внутренний размер элементов, в нашем случае это max-content размер. Это дает значение для сокращения пространства. Если бы элементы удаляли пространство только в соответствии с коэффициентом flex-shrink, тогда мелкие элементы могли бы исчезнуть, когда все их пространство было бы удалено, в то время как у большего элемента все еще было бы пространство для сжатия.

В этом цикле существует дополнительный шаг проверки элементов, которые станут больше или меньше их main size, в этом случае элемент перестает расти или сокращаться. Опять же, это делается для того, чтобы некоторые элементы не становились крошечными или массивными по сравнению с остальными предметами.

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

Если вы росли из auto, то flex-basis будет либо обрабатываться как любая ширина или высота элемента или max-content размер. Затем пространство будет удалено в соответствии с размером flex-basis, умноженным на коэффициент flex-shrink, и, следовательно, удаляется пропорционально максимальному размеру элементов.

Контроль роста и сжимания

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

Установив свой собственный flex-basis или предоставив самому элементу размер, который затем используется в качестве flex-basis, вы возвращаете управление алгоритмом, сообщая Flexbox, что вы хотите расти или уменьшаться от этого конкретного размера. Можно полностью отключить рост или сжатие, установив для параметра flex-grow или flex-shrink значение 0. На этом этапе, однако, стоит временно использовать желание контролировать flex элементы, чтобы проверить, используете ли вы правильный метод компоновки. Если вы пытаетесь выровнять элементы flex в двух измерениях, вам лучше выбрать макет сетки.

Вопросы отладки связанных размеров

Если ваши flex элементы заканчиваются неожиданными размерами, то это обычно происходит потому, что ваш flex-basis имеет auto, и есть что-то, что дает этому элементу ширину, которая затем используется в качестве flex-basis. Проверка элемента в DevTools может помочь определить, откуда берется размер. Вы также можете попробовать установить flex-basis в 0, который заставит Flexbox обрабатывать элемент как имеющий нулевую ширину. Даже если это не тот результат, который вы хотите, это поможет определить значение flex-basis в использовании в качестве виновника ваших проблем с размерами.

Flex зазоры

Очень востребованная функция Flexbox-это возможность указать зазоры или желоба между элементами flex таким же образом, как мы можем указать зазоры в макете сетки и макете с несколькими столбцами. Эта функция определена для Flexbox как часть Box Alignment, и первая реализация браузера на подходе. Firefox ожидает поставлять свойства gap для Flexbox в Firefox 63. Следующий пример можно посмотреть в Firefox Nightly.

Как изображение видно в браузере Firefox 63
Рис_5. Как изображение видно в Firefox 63

Как и при компоновке сетки, длина зазора учитывается перед распределением пространства для flex элементов.

Завершая

В этой статье я попыталась объяснить некоторые нюансы того, как Flexbox обрабатывает увеличение элементов flex. Это может показаться немного заумным, однако, потратив некоторое время, чтобы понять, как это работает, может сэкономить огромное количество времени при использовании Flexbox в ваших макетах. Я считаю, что очень полезно вернуться к тому факту, что по умолчанию Flexbox пытается дать вам наиболее разумную компоновку множества элементов с различными размерами. Если элемент содержит больше содержимого, ему предоставляется больше пространства. Если вы и ваш дизайнер не согласны с тем, что Flexbox считает лучшим, вы можете вернуть контроль, установив свое собственное значение для flex-basis.


ссылка на оригинал статьи https://habr.com/post/425977/

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *