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

Опубликовано: 2022-03-10
Краткое резюме ↬ В последних двух статьях мы рассмотрели, что происходит, когда мы создаем гибкий контейнер, а также рассмотрели выравнивание. На этот раз мы исследуем часто запутанную проблему изменения размеров во Flexbox. Как Flexbox решает, насколько большими должны быть объекты?

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

Начальное отображение элементов Flex

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

Три элемента с пробелом в конце
У гибких элементов есть место для отображения каждого в одной строке (большой предварительный просмотр)

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

Три элемента, последний элемент имеет более длинный текст и текст переносится
Пространство распределено, чтобы дать больше места для более длинного элемента (большой предварительный просмотр)

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

Еще после прыжка! Продолжить чтение ниже ↓

Спецификация внутренних и внешних размеров CSS

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

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

Предпочтительный размер блока — это размер, определяемый width или height , или логическими псевдонимами для этих свойств inline-size и block-size . Используя:

 .box { width: 500px; }

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

 .box { inline-size: 500px; }

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

минимальный размер содержимого

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

максимальный размер содержимого

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

Основной размер гибкого элемента

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

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

Определение размера элемента Flex

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

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

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

См. Pen Smashing Flexbox Series 3: flex: 1 1 0; Рэйчел Эндрю (@rachelandrew) на CodePen.

См. Pen Smashing Flexbox Series 3: flex: 1 1 0; Рэйчел Эндрю (@rachelandrew) на CodePen.

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

См. автоматический короткий текст Pen Smashing Flexbox Series 3: flex: 1 1 от Рэйчел Эндрю (@rachelandrew) на CodePen.

См. автоматический короткий текст Pen Smashing Flexbox Series 3: flex: 1 1 от Рэйчел Эндрю (@rachelandrew) на CodePen.

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

См. Pen Smashing Flexbox Series 3: flex: 1 1 auto long text от Рэйчел Эндрю (@rachelandrew) на CodePen.

См. Pen Smashing Flexbox Series 3: flex: 1 1 auto long text от Рэйчел Эндрю (@rachelandrew) на CodePen.

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

Определение Авто

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

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

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

Итак, если наша flex-basis имеет значение auto , Flexbox просматривает определенное свойство основного размера. У нас был бы основной размер, если бы мы дали любому из наших гибких элементов width . В приведенном ниже примере все элементы имеют ширину 110 пикселей, поэтому он используется в качестве основного размера, поскольку начальное значение для flex-basis — auto.

См. Pen Smashing Flexbox Series 3: гибкие элементы с шириной от Рэйчел Эндрю (@rachelandrew) на CodePen.

См. Pen Smashing Flexbox Series 3: гибкие элементы с шириной от Рэйчел Эндрю (@rachelandrew) на CodePen.

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

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

 .item { flex: 1 1 content; }

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

«Указывает автоматический размер на основе содержимого гибкого элемента. (Обычно он эквивалентен размеру максимального содержимого, но с корректировками для обработки соотношений сторон, внутренних ограничений размера и ортогональных потоков».

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

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

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

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

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

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

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

гибкие элементы с запасным пространством в конце
В первом случае у наших предметов есть место для роста. (Большой превью)

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

flex-элементы, переполняющие контейнер
Во втором случае наши элементы слишком велики и должны уменьшиться, чтобы поместиться в контейнер. (Большой превью)

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

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

См. Pen Smashing Flexbox Series 3: flex: 0 0 auto Рэйчел Эндрю (@rachelandrew) на CodePen.

См. Pen Smashing Flexbox Series 3: flex: 0 0 auto Рэйчел Эндрю (@rachelandrew) на CodePen.

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

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

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

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

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

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

Контроль роста и сокращения

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

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

Отладка проблем, связанных с размером

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

Гибкие зазоры

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

См. Pen Smashing Flexbox Series 3: flex-gaps Рэйчел Эндрю (@rachelandrew) на CodePen.

См. Pen Smashing Flexbox Series 3: flex-gaps Рэйчел Эндрю (@rachelandrew) на CodePen.
Три ряда элементов с промежутком между ними
Изображение в Firefox 63 (большой предварительный просмотр)

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

Подведение итогов

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