Флексбоксы ч.2
Обновлено
14.09.2023Просмотров
233Время прочтения
30 мин.Сложность
В предыдущем уроке мы рассмотрели свойства, которые применяются к флекс-контейнеру. Однако это далеко не все возможности флексов. В этом уроке речь пойдёт о свойствах, которые применяются непосредственно к самим флекс-элементам! При помощи них мы можем изменять индивидуальное поведение элементов, изменять их ширину, порядок отображения и пр.
flex-basis
Свойство устанавливает базовый размер флекс-элемента. Важно понимать, что это только базовый размер и это не означает, что элемент будет именно такого размера. Это не то же самое, что width или max-width для какого-либо из тегов. На итоговую ширину элемента влияет его содержимое, свойства width, max-width, flex-wrap, наличие\отсутствие свободного пространства, коэффициенты сжатия и роста, о которых мы поговорим позже. Как видите, факторов, влияющих на размер элемента, много, и разобраться в этом будет не просто.
Начнём с того, что по умолчанию работает значение auto, и это означает, что ширина элемента стремится к нулю. Разумеется, если там есть какой-то контент, то ширина не будет меньше этого контента.
Мы поместили текст в красный квадрат и задали ему 0 базовый размер. Как видите, элемент сжался максимально (до ширины самого длинного слова, его нельзя перенести), но не до нуля, потому что ему нужно как-то вмещать контент.
Вы также можете заметить, что для элемента по-прежнему указано width:80px, однако flex-basis является приоритетным. В случае, если flex-basis не указан или указано значение auto, размер будет зависеть от width.
При указании конкретного значения для flex-basis элемент будет стремиться к нему:
Элемент занял 50% от родительского размера. Да, как и для width, проценты считаются относительно родителя. Вы можете указать значение в любых величинах, которые понимает CSS — пикселях, поинтах, сантиметрах и пр.
В случае, если контент будет выходить за пределы элемента, элемент всё таки останется указанного размера:
Мы видим, что текст выходит за пределы элемента, но элемент не растягивается. Кстати, такая ситуация, когда контент выходит за пределы тега, называется переполнением (overflow) и об этом пойдёт речь в отдельном уроке.
В случае, когда наши элементы будут больше родителя и не будет flex-wrap, они будут сжиматься. Но сжиматься они будут по-разному, в зависимости от их flex-basis, width. В примере ниже мы убрали flex-wrap и задали flex-basis для красного квадрата 50%, а для двух других 30%:
В результате мы получили 110%, чего, разумеется, быть не может. Однако браузер должен что-то нам отображать. Он берёт ширину контейнера (300px), делит её на 110 и раздаёт каждому элементу согласно его ширине, указанной в процентах. То есть красный получит 50 * (300 / 110) = 136.4px. Два других квадрата будут по 30 * (300 / 110) = 81.8px. Если какая-то ширина будет указана в пикселях, она будет переводиться в проценты от родителя, затем будет проделана вышеуказанная операция рассчёта величины для всех элементов. Запоминать эту логику, конечно, не нужно. Нужно только понять, что браузер рассчитывает величину элементов исходя из указанных значений в flex-basis, width, а также исходя из размеров других элементов, распределяя размеры пропорционально.
Для flex-basis доступны значения min-content, max-content, fit-content и работают они схожим образом, как и для width. min-content будет стремиться как можно сильнее сжать содержимое. Если это текст, он будет переноситься на новые строки по одному\нескольким словам. При max-content наоборот элемент будет занимать столько места, сколько нужно для размещения контента, в случае с текстом для размещения его в одну строку:
Однако и тут элемент не будет выходить за пределы родителя.
Наконец, fit-content будет выбирать размер автоматически исходя из размеров контента. Это поведение похоже на max-content, но прочие элементы в контейнере, если им не будет хватать места, будут сжиматься не так сильно, как при max-content. Сжатие соседних элементов при fit-content:
И при max-content:
Как правило, настолько детально знать поведение флексов нет необходимости. Думаю, достаточно того, что вы видели и знаете, как это может работать. При создании макетов первое время обращайтесь к учебникам и справочникам.
order
Это свойство определяет положение флекс-элемента в строке. По умолчанию все флекс-элементы имеют нулевой индекс порядка, поэтому располагаются по оси так же, как идут в разметке. Однако мы можем указать для любого из элементов индекс, и тогда его расположение изменится. В примере мы задали order: 1 для синего квадрата и видим, что он теперь отображается не вторым, как идёт в разметке, а последним.
Значение для order может быть любым целым числом, в том числе отрицательным и нулём (по умолчанию ноль). Соответственно чем ниже значение, тем ближе элемент будет расположен к началу оси. Важно понимать, что речь идёт именно о начале оси, а не о расположении элементов слева\справа. Так, если наша ось будет направлена справа налево, то отрицательные значения order будут располагать элемент справа:
В примере мы видим, что направление оси задано справа налево. Ожидаемый порядок расположения квадратов — красный, синий, зелёный, но для зелёного задан order: -1, а значит он будет перемещён в начало оси. Результат — зелёный, красный, синий.
В случае, если у нас будут элементы с одинаковым индексом order, то их порядок между собой определяется их положением в разметке. Если мы зададим для синего квадрата также order: -1, то он будет располагаться в начале оси перед зелёным.
целое число, отрицательное, ноль или положительное | элемент с наименьшим индексом будет расположен в начале оси, с наибольшим — в конце. Значение по умолчанию для всех элементов — 0 |
inherit | Наследует значение от родителя |
initial | устанавливает значение свойства по умолчанию |
inherit | значение не установлено. Поскольку свойство не является наследуемым, принимает значение по умолчанию, то есть 0 |
align-self
В предыдущем уроке мы рассматривали вертикальное выравнивание элементов в строке при помощи свойства align-items. Однако есть ещё одно свойство, которое позволяет изменять такое выравнивание для отдельного элемента.
На скриншоте мы выравниваем элементы по центру контейнера, а для синего квадрата указываем align-self: baseline. В результате, как и ожидалось, синий элемент получает собственное выравнивание по базовой линии:
Логично, что значения для данного свойства будут такими же, как и для align-items.
Мы можем указывать разные выравнивания для разных блоков, например так:
Как видите, теперь блоки выравниваются каждый по-своему, в то время как для контейнера указано выравнивание по центру. Всё это позволяет нам действовать ещё более гибко, формируя различные модели интерфейсов.
flex-grow
Это коэффициент роста, и здесь нам нужно снова обратиться к понятию «свободное пространство». Коэффициент роста имеет какую-то силу только при наличии свободного пространства. Если такового нет, то наличие коэффициента не окажет никакого влияния на отображение элементов.
В обратном случае элемент будет увеличиваться пропорционально своему коэффициенту роста.
Вернёмся к исходному примеру и вспомним, что наш контейнер равен по ширине 300, а блоки по 80, итого у нас остаётся 60px свободного пространства. При указании коэффициента роста для красного блока он вырастает и занимает всё свободное пространство:
По умолчанию коэффициент равен 0, и поэтому никакие блоки не растут, даже если свободное пространство есть. Однако если мы указываем иной коэффициент, блок вырастает, причём расти он будет пропорционально этому коэффициенту.
Мы указали коэффициент роста также для синего блока, и теперь вы можете заметить, что свободное пространство распределяется поровну между красным и синим блоками. Это справедливо, поскольку их коэффициенты равны. Логика работы CSS в данном случае следующая: взять свободное пространство и поделить его на сумму коэффициентов роста, затем эту величину отдать каждому из элементов. Например, свободное пространство 100px / 2 = 50px. Каждый из блоков с flex-grow: 1 получит дополнительно по 50px ширины.
В следующем примере мы указываем для синего блока коэффициент роста 2:
Теперь видим, что свободное пространство распределилось по такому же принципу и синий получил больше, чем красный. Зелёный не получил ничего, т.к. имеет коэффициент роста 0.
Коэффициент роста работает в пределах строки, на которой находится элемент. В примере у нас зелёный блок находится на следующей строке и для него задан flex-grow:
Логично, что он незанимает часть строки, на которой находятся два других блока. Если мы укажем для красного или синего также flex-grow, то этот блок займёт свободное пространство своей строки.
Помимо целого числа, вы можете указать для блока дробное число до единицы, это будет означать, что он занимает N-часть свободного пространства. Например, при указании flex-grow: 0.5 он займёт 50% свободного пространства:
Если мы укажем ещё для одного элемента flex-grow: 0.3, то каждый элемент займёт соответствующее количество свободного пространства:
Однако 20% ещё останется свободным, поскольку общий коэффициент всех блоков не превышает 1. Думаю, логика работы тут понятна.
положительное целое, дробное число или ноль | элемент получает соответствующую его коэффициенту часть свободного пространства. При сумме значений коэффициентов меньше единицы они занимают менее 100% свободного пространства. Значение по умолчанию — 0 |
inherit | Наследует значение от родителя |
initial | устанавливает значение свойства по умолчанию |
inherit | значение не установлено. Поскольку свойство не является наследуемым, принимает значение по умолчанию, то есть 0 |
flex-shrink
Подобно тому, как существует коэффициент роста, существует и коэффициент сжатия. Его работа также полностью связана со свободным пространством, однако в этот раз для нас важно его отсутствие. Когда наш контейнер меньше необходимой для элементов ширины и нет flex-wrap: wrap, элементы сжимаются на какую-то величину в зависимости от своего предполагаемого размера. Так, в нашем примере все три блока сожмутся одинаково и будут равны 66.6px:
В случае, когда мы хотим сжать какой-либо блок сильнее, чем другие, мы должны использовать коэффициент сжатия. Укажем для синего коэффицент 2 (по умолчанию у всех тегов он равен 1!):
И теперь можно заметить, что синий при недостатке свободного пространства сжался сильнее, чем красный или зелёный. Его размер теперь 60px, а красного и зелёного — по 70px. Логика рассчёта сжатия в CSS в данном случае следующая: размер контейнера 200, а размер элементов 80 * 3 = 240. Итого нам не хватает 40px. Сумма коэффициентов сжатия будет 4 (2 от синего, 1 от красного и 1 от зелёного), поэтому браузер делит 40 px / 4 и получается 10px — это величина, на которую будет сжат элемент с коэффициентом 1. Соответственно, при коэффициенте 2 элемент будет сжат на 20px. Думаю, с этим понятно.
Можно указывать и дробное число, однако логика работы вовсе не поменяется, просто элемент получит ещё больше сжатия. Всё остальное будет работать и рассчитываться по вышеописанному алгоритму.
Вы можете указывать различные коэффициенты для различных флекс-элементов, таким образом довольно гибко управляя сжатием.
положительное целое или дробное число, но не ноль | Элемент сжимается сильнее с большим коэффициентом. Степень сжатия зависит от недостатка свободного пространства и коэффициента. Значение по умолчанию — 1 |
inherit | Наследует значение от родителя |
initial | устанавливает значение свойства по умолчанию |
inherit | значение не установлено. Поскольку свойство не является наследуемым, принимает значение по умолчанию, то есть 1 |
flex
Это свойство является сокращением для указания одновременно трёх свойств: flex-grow, glex-shrink, flex-basis. Значения по умолчанию flex: 0 1 auto.
Вы можете указывать, разумеется, как одну, так и несколько величин. В зависимости от количества они будут применяться к тому или иному свойству:
<style>
.container{
/* эквивалент 0 0 auto */
flex: none;
/* одно значение с указанием единиц, flex-basis */
flex: 10rem;
flex: 30%;
/* ключевое слово, подходящее для flex-basis */
flex: min-content;
/* два значения, одно с указанием единиц, flex-grow | glex-basis */
flex: 1 30px;
/* два значения без указания единиц, flex-grow | flex-shrink */
flex: 1 2;
/* три значения, flex-grow | flex-shrink | flex-basis */
flex: 1 2 30%;
}
</style>
Думаю,с этим всё должно быть понятно: CSS сам анализирует, какие и сколько значений вы указали и применяет их к тем или иным свойствам. Будьте внимательны и первое время не полагайтесь на память, заглядывайте в справочник.
Также, разумеется, доступны и глобальные значения.
одно или несколько значений, ключевых слов | применяются к одному или нескольким свойствам, см. разъяснения выше. По умолчанию 0 1 auto |
inherit | Наследует значение от родителя |
initial | устанавливает значение свойства по умолчанию |
inherit | значение не установлено. Поскольку свойство не является наследуемым, принимает значение по умолчанию, то есть 0 1 auto |
Несмотря на то, что флексбоксы поддерживаются достаточно, чтобы вы могли их применять без каких-либо опасений, они нуждаются в добавлении префиксов. Используйте соответствующие инструменты или сборщики. Также будьте готовы к тому, что некоторые свойства называются в разных браузерах по-разному. Это также обычно учитывается автопрефиксерами и сборщиками.