Как работает flex-shrink в CSS. Подробное руководство

Stas Bagretsov
4 min readJan 19, 2018

--

Flex-shrink это подсвойство, которое помогает в создании шаблона страницы с помощью Flex-box.

Оно определяет фактор “нарезки” элемента, который указывает на сколько “flex частей” будет уменьшаться элемент относительно других элементов в flex-контейнере, в тех случаях, когда для него недостаточно места в этом самом контейнере.

Когда этот параметр не указан в CSS файле, то он по-дефолту выставлен на 1 и фактор “нарезки” умножается на показатель flex-basis, когда распределяется отрицательное пространство.

👉Мой Твиттер — там много из мира фронтенда, да и вообще поговорим🖖. Подписывайтесь, будет интересно: ) ✈️

#Синтаксис

flex-shrink: <число>.flex-item { flex-shrink: 2;}

#Демо

Чтобы увидеть, как это всё происходит на наглядном, живом примере, вам нужно самим изменять размер ширины контейнеры. Поэтому зайдите свои параметры на CodePen и поиграйтесь с шириной окна.

Что мы видим в этой демке?

Первый элемент имеет значение flex: 1 1 20em, что в обычном виде означает flex-grow:1, flex-shrink:1, flex-basis: 20em.

Второй элемент имеется значения flex: 2 2 20em, что в обычном виде означает flex-grow:2, flex-shrink: 2, flex-basis: 20em.

Оба flex элемента хотят быть по 20em в ширину. Из-за flex-grow(первое значение), если сам flex контейнер больше 40em, второй дочерний элемент получит вдвое больше оставшегося места, чем первый дочерний элемент. Но если родительский элемент меньше, чем 40em, тогда второй дочерний элемент будет в два раза урезан в отношении первого дочернего элемента, на фоне которого он будет смотреться меньше. Это произойдет из-за второго значения во flex, flex-shrink. В общем-то все и так понятно, но как и в случае с flex-grow, не все так просто. Давайте посмотрим как высчитывается flex-shrink.

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

По некоторым причинам, метод работы с flex-shrink отличается от flex-grow и немного сложнее.

Как вы уже наверное догадались, flex решает буквально все проблемы раскладки во фронт-энде.

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

В общем, в этом и суть flex-shrink.

Ещё раз упомянем, что возможно вы думали о том, что flex-shrink высчитывается также, как и flex-grow, но тут всё не так то просто.

Свойство flex-shrink указывает на то, насколько каждый элемент урежется при нехватке свободного места. Его стандартное значение равно 1. Множество статей просто описывают это свойство как «коэффициент сокращения элемента» и всё. Нет ни слова о том, как он высчитывается.

flex-shrink определяет только важность компонента при его сжатии, если ширина меньше.

Для примера:

Родительский элемент имеет ширину в 500px. Другие три дочерних элемента выставлены на 150px, 200px и 300px.

У flex элементов стоят flex-shrink значения 1, 2 и 3, соответственно.

Давайте сначала посчитаем переполнение элементов в контейнере: 150 + 200 + 300–500 = -150px.

Далее, эти -150px будут компенсированы сокращением на определенное количество для каждого из трех элементов.

Вычисления тут такие: каждый элемент сокращается в соответствии со своим flex-shrink, умноженным на его ширину.

В общем, общий «вес» получается таким: 1 * 150 + 2 * 200 + 3 * 300 = 1450

Значит, каждый элемент сократится так:

150 * 1(flex-shrink) * 150(width) / 1450 = -15.5

150 * 2(flex-shrink) * 200(width) / 1450 = -41.4

150 * 3(flex-shrink) * 300(width) / 1450 = -93.1

И финальные размеры будут такими:

150–15.5 = 134.5

200–41.4 = 158.6

300–93.1 = 206.9

.flex-container{display: flex; width: 500px;} .flex-item-1{ flex-basis: 150px; flex-shrink: 1;}  .flex-item-2{ flex-basis: 200px; flex-shrink: 2;}  .flex-item-3{ flex-basis: 300px; flex-shrink: 3;}
Не обращайте внимания на мелкие неточности, в виде одних сотых пикселя -это из-за размеров браузера

Примерно также, когда сумма всех flex-shrink всех элементов меньше 1, вычисления будут другими:

Тут он не будет сокращать всё место, а только обрежет место в соотношении flex-shrink к значению 1.

Тот же самый пример, но flex-shrink значения у каждого элемента будут изменены на 0.1, 0.2 и 0.3, соответственно.

Тогда общий «вес» будет 145 (просто в 10 раз меньше, формулу пропускаем).

Все три элемента сокращаются не на 150px, а только на 150px (0.1 + 0.2 + 0.3) / 1 или на 60% всего места: 90px.

Место на которое нарезается каждый элемент:

90 * 0.1(flex-shrink) * 150(width) / 145 = 9.31

90 * 0.2(flex-shrink) * 200(width) / 145 = 24.83

90 * 0.3(flex-shrink) * 300(width) / 145 = 55.86

И конечная ширина элементов:

150–9.31 = 140.69

200–24.83 = 175.17

300–55.86 = 244.14

Конечно же, как и на flex-grow, min-width влияет на flex-shrink.

.flex-container{display: flex; width: 500px;}.flex-item-1{ flex-basis: 150px; flex-shrink: 0.1;}.flex-item-2{ flex-basis: 200px; flex-shrink: 0.2;}.flex-item-3{ flex-basis: 300px; flex-shrink: 0.3;}
Не обращайте внимания на мелкие неточности, в виде одних сотых пикселя -это из-за размеров браузера

--

--

Stas Bagretsov

Надеюсь верую вовеки не придет ко мне позорное благоразумие. webdev/sports/books