Понимание Flexbox более глубоко
С тех пор, как появился display: flex
, создание макетов с использованием CSS стало легким делом. Одной из сложных вещей всегда было понять, как работают flex-grow
и flex-shrink
. Какая математика стоит за ними? Это моя попытка их упростить.
Часть 1. Введение
Мы начнем с базовой страницы, родительского блока div, содержащего три элемента div: один, два и три соответственно. Один, два и три имеют высоту 100 пикселей и ширину 50 пикселей. Посмотрите на следующую картинку (код будет следовать).
Как мы видим, у нас есть родительский div и три дочерних div с красным, синим и зеленым цветами соответственно. Родительский div имеет желтый цвет.
Приведенный выше файл ляжет в основу нашей будущей статьи. Я буду отображать только макеты и соответствующий CSS. Остальной код останется прежним.
Часть 2. Flex-Grow
Давайте дадим каждому дочернему div свойство flex-grow
1.
Макет выглядит следующим образом. Как и ожидалось, все три блока выросли одинаково, разделив между собой пространство, оставшееся в родительском блоке.
В следующем примере давайте присвоим значения 1, 2 и 3 красному, синему и зеленому цветам соответственно.
Как видим, все трое выросли на разную величину. Их размеры:
- Красный: 104,5 (рост на 54,5)
- Синий: 159 (рост на 109)
- Зеленый: 213,5 (рост на 163,5)
- Родительский размер: 477 (свободное пространство, занятое с использованием
flex-grow
, составляет 227)
Как мы видим, пространство, которое было доступно дочерним div, пропорционально делится в соответствии со значением flex-grow
.
- Красный: 277 * (1/6) = 54,5
- Синий: 277 * (2/6) = 109
- Зеленый: 277 * (3/6) = 163,5
Примечание. Ваши значения будут отличаться в зависимости от размера экрана. По умолчанию flex-grow
равно нулю.
Формула для flex-grow
:
Доступное пространство * (flex-grow
значение дочернего элемента / сумма всех flex-grow
значений)
Часть 3. Флекс-термоусадка.
Давайте сделаем что-нибудь интересное и сделаем значение ширины родительского элемента равным 100 пикселей. Это сделает родительское значение на 50 пикселей меньше, чем общее значение его дочерних элементов.
Как видим, все трое детей уменьшились в размерах. Все они теперь имеют размер 33,33. Значение по умолчанию flex-shrink
- 1. Поскольку свободного места не было, они уменьшились, чтобы освободить 50 пикселей в пространстве.
Сделаем flex-shrink
значение 1,2 и 3 соответственно для детей.
Как видим, все трое уменьшились и теперь имеют разные размеры. Красный имеет наименьшее значение flex-shrink
(наименьшее сжатие), а зеленый - наибольшее значение flex-shrink
(наибольшее сжатие).
Посмотрим на их размеры.
- Красный: 41,6667 (уменьшился на 8,3333)
- Синий: 33,3333 (уменьшение на 16,6667)
- Зеленый: 25 (уменьшился на 25)
- Родительский размер: 100 пикселей (дети должны освободить 50 пикселей в пространстве)
Как мы видим, объем пространства, освобожденного дочерними элементами, пропорционален их значению flex-shrink
: у красного меньше всего, поэтому он меньше всего сжимается, а у зеленого больше и меньше всего.
- Красный: 50 * (1/6) = 8,3333
- Синий: 50 * (2/6) = 16,6667
- Зеленый: 50 * (3/6) = 25
Формула уменьшения размера:
Освобождаемое пространство * (flex-shrink
значение дочернего элемента / сумма всех flex-shrink
значений)
Интересно то, что рост всех троих детей разный. Сделаем их 40, 50 и 60 соответственно.
На этом изображении сложно наблюдать, но мы видим, что зеленый ребенок уменьшился менее чем на 25 пикселей, как и раньше. Посмотрим на их размеры.
- Красный: 26,6667 (уменьшился на 13,3333)
- Синий: 33,3333 (уменьшение на 16,6667)
- Зеленый: 40 (уменьшился на 20)
Как мы видим, все три имеют одинаковые значения flex-shrink
, но все уменьшились на разные значения. Легко заметить, что они уменьшились пропорционально своему размеру. Красный сжался меньше всего, так как был самым маленьким, а зеленый сжался больше всего, потому что он был самым большим.
- Красный: 50 * (40/150) = 13,3333
- Синий: 50 * (50/150) = 16,6667
- Зеленый: 50 * (60/150) = 20
Теперь давайте изменим их flex-shrink
значения на 3,2 и 1, чтобы сделать вещи немного интереснее, и сведем их к окончательной формуле.
Посмотрим на их размеры.
- Красный: 18,5667 (уменьшение на 21,4333)
- Синий: 32,15 (уменьшение на 17,85)
- Зеленый: 49,2833 (уменьшился на 10,7167)
Все трое уменьшились пропорционально своим размерам и их flex-shrink
значениям. На этот раз формула немного отличается. Они уменьшились пропорционально кратному значению flex-shrink
и его размеру.
Множители составляют 40 * 3 для красного, 50 * 2 для синего и 60 * 1 для зеленого.
- Красный: 50 * (120/280) = 21,43333
- Синий: 50 * (100/280) = 17,85
- Зеленый: 50 * (60/280) = 10,7167
Формула для flex-shrink
:
Общее пространство, подлежащее уменьшению * [flex-shrink
значение * начальная ширина / сумма (flex-shrink
значение * начальное значение) всех элементов]
Часть 4. Еще несколько примеров
Часть 5. flex-direction и flex-base.
В приведенном выше примере все было вычислено по ширине. Это потому, что по умолчанию основная ось была горизонтальной, поскольку flex-direction
было строкой. Если flex-direction
- столбец, основная ось становится вертикальной, а flex-grow
и flex-shrink
изменяют высоту элемента, а не ширину элемента.
Давайте посмотрим на пример. Высота родительского элемента составляет 300 пикселей, а flex-direction
- столбец. Красный, Синий и Зеленый имеют высоту 50 пикселей соответственно.
Если я добавлю к дочерним элементам flex-grow
свойств, они будут расти в вертикальном направлении, поскольку flex-direction
- столбец.
Flex-basis
- это начальная длина ширины или высоты, в зависимости от flex-direction
. Для строки это ширина. Для столбца это высота.
Сокращение для записи свойств гибкости:
flex: 1 1 100; # flex-grow flex-shrink flex-basis
Есть еще четыре свойства, которые можно использовать для ребенка. Это min-width
, max-width
, min-height
и max-height
. Дочерний элемент останется ограниченным в этих четырех.
Дочернему элементу автоматически присваивается свойство отображения flex-item
.
Часть 6. Заключение
Надеюсь, вам понравилась эта статья и что она была достаточно простой для понимания. Если у вас есть вопросы, оставьте, пожалуйста, комментарий.