Понимание 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. Заключение
Надеюсь, вам понравилась эта статья и что она была достаточно простой для понимания. Если у вас есть вопросы, оставьте, пожалуйста, комментарий.