Фактор сжимаемости флекс блоков

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

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

Давайте произведем некоторый расчет. Пусть, к примеру, у нас есть 4 элемента шириной в 200px. Пусть при этом ширина родителя равна 700px. Получается, что суммарная ширина элементов равна:

200px * 4 = 800px

Это ширина на 100px больше ширины родителя. Давайте вычислим, сколько от каждого элемента надо отщипнуть, чтобы элементы поместились в своего родителя:

100px / 4 = 25px

То есть ширина элементов будет:

200px - 25px = 175px

Реализуйте описанные блоки и проверьте измерением, что ширина элементов будет действительно равна рассчитанной нами.

Рассчитайте ширину блоков, а затем проверьте расчеты измерением:

<div class="parent"> <div class="child elem1">1</div> <div class="child elem2">2</div> <div class="child elem3">3</div> </div> .parent { display: flex; width: 200px; height: 200px; border: 1px solid red; } .child { height: 50px; border: 1px solid green; } .elem1 { width: 100px; } .elem2 { width: 100px; } .elem3 { width: 100px; }

Разная ширина элементов

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

Пусть у нас есть 4 элемента. Пусть ширина первого элемента равна 400px, ширина остальных элементов - 200px, а ширина родителя 900px.

Суммарная ширина элементов равна:

400px + 3 * 200px = 1000px

Тогда отрицательное свободное пространство будет равно:

1000px - 900px = 100px

Найдем сколько отщипнется первого элемента:

100px * (400px / 1000px) = 40px

То есть его ширина будет равна:

400px - 40px = 360px

Найдем сколько от каждого из остальных элементов:

100px * (200px / 1000px) = 20px

То есть ширина этих элементов будет равна:

200px - 20px = 180px

Реализуйте описанные блоки и проверьте измерением, что ширина элементов будет действительно равна рассчитанной нами.

Рассчитайте ширину блоков, а затем проверьте расчеты измерением:

<div class="parent"> <div class="child elem1">1</div> <div class="child elem2">2</div> <div class="child elem3">3</div> </div> .parent { display: flex; width: 300px; height: 200px; border: 1px solid red; } .child { height: 50px; border: 1px solid green; } .elem1 { width: 300px; } .elem2 { width: 100px; } .elem3 { width: 100px; }

Регулируем сжатие

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

Данное свойство представляет собой некоторый вес, на который будет умножаться ширина элемента при подсчете отщипываемого кусочка по уже приведенной выше формуле. К примеру, если ширина элемента равна 200px, а его flex-shrink равен 3, то взвешенная (т.е. умноженная на вес) ширина элемента получится равна:

200px * 3 = 600px

Формула с учетом flex-shrink будет иметь следующий вид: отриц. св. пространство * (взвешенная ширина элемента / сумма всех взвеш. ширин элементов).

Давайте посмотрим на примере. Пусть у нас есть 4 элемента. Пусть ширина первого элемента равна 400px, а flex-shrink равен 2, ширина остальных элементов - 200px, а их flex-shrink равен 1. Пусть ширина родителя 900px.

Суммарная ширина элементов равна:

400px + 3 * 200px = 1000px

Отрицательное свободное пространство будет равно:

1000px - 900px = 100px

Суммарная взвешенная ширина элементов равна:

400px * 2 + 200px * 1 + 200px * 1 + 200px * 1 = 1400px

Взвешенная ширина первого элемента равна:

400px * 2 = 800px

От первого элемента отщипнется следующий кусочек:

100px * (800px / 1400px) = 100px * 0.57 = 57.14px

Ширина элемента будет равна:

400px - 57.14px = 342.86px ~ 343px

Взвешенная ширина каждого из остальных элемента равна:

200px * 1 = 200px

От каждого элемента отщипнется следующий кусочек:

400px - 57.14px = 342.86px ~ 343px

Ширина элемента будет равна:

200px - 14.2px = 185.8px ~ 186px

Реализуйте описанные блоки и проверьте измерением, что ширина элементов будет действительно равна рассчитанной нами.

Рассчитайте ширину блоков, а затем проверьте расчеты измерением:

<div class="parent"> <div class="child elem1">1</div> <div class="child elem2">2</div> <div class="child elem3">3</div> </div> .parent { display: flex; width: 200px; height: 200px; border: 1px solid red; } .child { height: 50px; border: 1px solid green; } .elem1 { width: 100px; flex-shrink: 2; } .elem2 { width: 100px; flex-shrink: 1; } .elem3 { width: 100px; flex-shrink: 1; }

Рассчитайте ширину блоков, а затем проверьте расчеты измерением:

<div class="parent"> <div class="child elem1">1</div> <div class="child elem2">2</div> <div class="child elem3">3</div> </div> .parent { display: flex; width: 200px; height: 200px; border: 1px solid red; } .child { height: 50px; border: 1px solid green; } .elem1 { width: 100px; flex-shrink: 3; } .elem2 { width: 100px; flex-shrink: 2; } .elem3 { width: 100px; flex-shrink: 1; }

Рассчитайте ширину блоков, а затем проверьте расчеты измерением:

<div class="parent"> <div class="child elem1">1</div> <div class="child elem2">2</div> <div class="child elem3">3</div> <div class="child elem4">4</div> </div> .parent { display: flex; width: 500px; height: 200px; border: 1px solid red; } .child { height: 50px; border: 1px solid green; } .elem1 { width: 300px; flex-shrink: 3; } .elem2 { width: 200px; flex-shrink: 2; } .elem3 { width: 200px; flex-shrink: 1; } .elem4 { width: 200px; flex-shrink: 1; }

Нюансы

Свойство flex-shrink по умолчанию имеет значение 1 - именно поэтому элементы сжимаются. Чтобы отменить сжатие, нужно установить это свойство в значение 0. Кроме того, можно давать дробные значения, например, 0.5 или 1.5.