Как работает flex-shrink в CSS. Подробное руководство
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;}