flex
и flex
— это CSS-свойства, определяющие, какое количество свободного пространства флекс-контейнера может занимать текущий элемент.
Рассмотрим каждое свойство в отдельности.
flex-grow
СкопированоСоздадим флекс-контейнер с двумя вложенными элемента с разными значениями flex
.
<div class="container"> <code class="container-item-grown">flex-grow: 2;</code> <code class="container-item-common">flex-grow: 1;</code></div>
<div class="container"> <code class="container-item-grown">flex-grow: 2;</code> <code class="container-item-common">flex-grow: 1;</code> </div>
.container { display: flex; width: 1200px; height: 100px;}.container-item-grown { background-color: #2E9AFF; flex-grow: 2;}.container-item-common { background-color: #F498AD; flex-grow: 1;}
.container { display: flex; width: 1200px; height: 100px; } .container-item-grown { background-color: #2E9AFF; flex-grow: 2; } .container-item-common { background-color: #F498AD; flex-grow: 1; }
У нас есть контейнер шириной 1200 px, для первого элемента указан flex
, а для второго — flex
. Первый элемент занимает 800 px, а второй 400 px.
Хочется думать, что здесь всё просто и работает по правилам математики:
- сложить значения свойства для каждого контейнера и получить 3 (2 + 1);
- поделить ширину контейнера на общее количество «частей» и получить 400 px (1200 px / 3);
- для каждого блока использовать значение
flex
как вес и умножить на ширину одной части;- grow - для первого блока 400 px * 2 = 800 px;
- для второго блока 400 px * 1 = 400 px.
Пока всё верно. Однако, часто на практике мы ожидаем, что сейчас мы укажем flex
и это нас спасёт и… не работает.
Вот пример, такого «не работает».
<div class="container"> <div class="container-item-grown"> <p> Равным образом сложившаяся структура организации требуют определения и уточнения модели развития. Повседневная практика показывает, что дальнейшее развитие различных форм деятельности обеспечивает широкому кругу (специалистов) участие в формировании систем массового участия. </p> </div> <div class="container-item-common"> <p> Равным образом сложившаяся структура организации требуют определения и уточнения модели развития. Повседневная практика показывает, что дальнейшее развитие различных форм деятельности обеспечивает широкому кругу (специалистов) участие в формировании систем массового участия. </p> </div></div>
<div class="container"> <div class="container-item-grown"> <p> Равным образом сложившаяся структура организации требуют определения и уточнения модели развития. Повседневная практика показывает, что дальнейшее развитие различных форм деятельности обеспечивает широкому кругу (специалистов) участие в формировании систем массового участия. </p> </div> <div class="container-item-common"> <p> Равным образом сложившаяся структура организации требуют определения и уточнения модели развития. Повседневная практика показывает, что дальнейшее развитие различных форм деятельности обеспечивает широкому кругу (специалистов) участие в формировании систем массового участия. </p> </div> </div>
.container { display: flex; width: 1200px;}.container-item-grown { background-color: #2E9AFF; flex-grow: 2;}.container-item-common { background-color: #F498AD; flex-grow: 1;}
.container { display: flex; width: 1200px; } .container-item-grown { background-color: #2E9AFF; flex-grow: 2; } .container-item-common { background-color: #F498AD; flex-grow: 1; }
Пример отличается от предыдущего тем, что в блоках появился текст, обёрнутый в параграф. И результат таков, что блоки стали одинаковыми по ширине.
Получается, что логика рассуждений, приведённая выше, не работает?
Не совсем так, давайте разбираться.
Деталь кроется в том, что flex
определяет, какое количество свободного места занимает элемент. И если внимательно посмотреть, то каждый блок текста занял по 600 px ширины, а свободного пространства не осталось. Поэтому и распределять нечего.
Почему же в первом примере всё работает ожидаемо? Там логика сработала, потому что для блоков не указана ширина и в них нет вложенных элементов, а значит ширина обоих 0 px, и свободное место — это и есть ширина контейнера, то есть 1200 px.
И что, если свободного места нет, то использовать flex
не получится? Не совсем, нужно просто добавить свойство flex
. Если использовать эти свойства в комплекте, то алгоритм расчёта ширины изменится.
flex
— это свойство, которое устанавливает начальный основной размер флекс-элемента. Его можно задать в любых единицах, в которых можно задать ширину элемента.
В результате мы получим то, чего хотим.
<div class="container"> <div class="container-item-grown"> <p> Равным образом сложившаяся структура организации требуют определения и уточнения модели развития. Повседневная практика показывает, что дальнейшее развитие различных форм деятельности обеспечивает широкому кругу (специалистов) участие в формировании систем массового участия. </p> </div> <div class="container-item-common"> <p> Равным образом сложившаяся структура организации требуют определения и уточнения модели развития. Повседневная практика показывает, что дальнейшее развитие различных форм деятельности обеспечивает широкому кругу (специалистов) участие в формировании систем массового участия. </p> </div></div>
<div class="container"> <div class="container-item-grown"> <p> Равным образом сложившаяся структура организации требуют определения и уточнения модели развития. Повседневная практика показывает, что дальнейшее развитие различных форм деятельности обеспечивает широкому кругу (специалистов) участие в формировании систем массового участия. </p> </div> <div class="container-item-common"> <p> Равным образом сложившаяся структура организации требуют определения и уточнения модели развития. Повседневная практика показывает, что дальнейшее развитие различных форм деятельности обеспечивает широкому кругу (специалистов) участие в формировании систем массового участия. </p> </div> </div>
.container { display: flex; width: 1200px;}.container-item-grown { background-color: #2E9AFF; flex-grow: 2; flex-basis: 800px;}.container-item-common { background-color: #F498AD; flex-grow: 1; flex-basis: 400px;}
.container { display: flex; width: 1200px; } .container-item-grown { background-color: #2E9AFF; flex-grow: 2; flex-basis: 800px; } .container-item-common { background-color: #F498AD; flex-grow: 1; flex-basis: 400px; }
Ещё один пример без flex
для закрепления. Попробуем задать ширину параграфов: для первого параграфа зададим 300 px, а для второго 600 px.
<div class="container"> <div class="container-item-grown"> <p> Равным образом сложившаяся структура организации требуют определения и уточнения модели развития. Повседневная практика показывает, что дальнейшее развитие различных форм деятельности обеспечивает широкому кругу (специалистов) участие в формировании систем массового участия. </p> </div> <div class="container-item-common"> <p> Равным образом сложившаяся структура организации требуют определения и уточнения модели развития. Повседневная практика показывает, что дальнейшее развитие различных форм деятельности обеспечивает широкому кругу (специалистов) участие в формировании систем массового участия. </p> </div></div>
<div class="container"> <div class="container-item-grown"> <p> Равным образом сложившаяся структура организации требуют определения и уточнения модели развития. Повседневная практика показывает, что дальнейшее развитие различных форм деятельности обеспечивает широкому кругу (специалистов) участие в формировании систем массового участия. </p> </div> <div class="container-item-common"> <p> Равным образом сложившаяся структура организации требуют определения и уточнения модели развития. Повседневная практика показывает, что дальнейшее развитие различных форм деятельности обеспечивает широкому кругу (специалистов) участие в формировании систем массового участия. </p> </div> </div>
.container { display: flex; width: 1200px;}.container-item-grown { background-color: #2E9AFF; flex-grow: 2;}.container-item-common { background-color: #F498AD; flex-grow: 1;}.container-item-grown p { width: 300px;}.container-item-common p { width: 600px;}
.container { display: flex; width: 1200px; } .container-item-grown { background-color: #2E9AFF; flex-grow: 2; } .container-item-common { background-color: #F498AD; flex-grow: 1; } .container-item-grown p { width: 300px; } .container-item-common p { width: 600px; }
Здесь получается не совсем ожидаемый от flex
результат, если не знать как работает свойство на самом деле. Но мы-то уже знаем, давайте посчитаем:
- Первый блок занимает 300 px. Это свойство задано для селектора
p
. - Второй блок занимает 600 px. Причина всё та же — так задано в дочернем элементе.
- Итого, для распределения свойством
flex
остаётся 300 px. Далее применим логику, которая была описана чуть выше, и…- grow - На первый элемент придётся 200 px, а на второй — всего 100 px.
- В итоге первый элемент займёт 500 px (300 px + 200 px), а второй - 700 px (600 px + 100 px).
Что ещё здесь важно помнить?
СкопированоКак работает свойство box-sizing. Вычисление свойства flex
также, как и свойства width
зависит от box
, и результат, в зависимости от указанного значения, будет разным.
flex-shrink
СкопированоТеперь посмотрим на свойство flex-shrink. Его мы используем в тех случаях, когда места не хватает и размеры элементов флекс-контейнера нужно уменьшить. Здесь математика чуть сложнее, вот пример:
<div class="container"> <div class="container-item-shrinked"> <p> Равным образом сложившаяся структура организации требуют определения и уточнения модели развития. Повседневная практика показывает, что дальнейшее развитие различных форм деятельности обеспечивает широкому кругу (специалистов) участие в формировании систем массового участия. </p> </div> <div class="container-item-common"> <p> Равным образом сложившаяся структура организации требуют определения и уточнения модели развития. Повседневная практика показывает, что дальнейшее развитие различных форм деятельности обеспечивает широкому кругу (специалистов) участие в формировании систем массового участия. </p> </div></div>
<div class="container"> <div class="container-item-shrinked"> <p> Равным образом сложившаяся структура организации требуют определения и уточнения модели развития. Повседневная практика показывает, что дальнейшее развитие различных форм деятельности обеспечивает широкому кругу (специалистов) участие в формировании систем массового участия. </p> </div> <div class="container-item-common"> <p> Равным образом сложившаяся структура организации требуют определения и уточнения модели развития. Повседневная практика показывает, что дальнейшее развитие различных форм деятельности обеспечивает широкому кругу (специалистов) участие в формировании систем массового участия. </p> </div> </div>
.container { display: flex; width: 800px;}.container-item-shrinked { background-color: #2E9AFF; flex-shrink: 2; flex-basis: 400px;}.container-item-common { background-color: #F498AD; flex-shrink: 1; flex-basis: 800px;}
.container { display: flex; width: 800px; } .container-item-shrinked { background-color: #2E9AFF; flex-shrink: 2; flex-basis: 400px; } .container-item-common { background-color: #F498AD; flex-shrink: 1; flex-basis: 800px; }
У нас в примере два элемента, у каждого есть изначальная ширина (flex
равен 400 px и 800 px соответственно). Итого 1200 px. Однако ширина флекс-контейнера всего 800 px.
Сначала посчитаем общий вес при том, что для первого элемента значение flex
составляет 2, а для второго — 1: 2 * 400 px + 1 * 800 px = 1600 px.
Для полноценного размещения нам не хватает 1200 px - 800 px = 400 px.
Подсчёт сокращения будет выглядеть следующим образом:
- Пространство, которого не хватает, умножим на значение
flex
.- shrink - Затем результат умножим на значение
flex
.- basis - Результат предыдущего действия разделим на общий вес.
Считаем:
- 400 px * 2 * 400 px / 1600 px = 200 px
- 400 px * 1 * 800 px / 1600 px = 200 px
А в результате ширина блоков будет следующая:
- 400 px - 200 px = 200 px
- 800 px - 200 px = 600 px
Вывод: с помощью свойств flex
, flex
, flex
можно предусмотреть как ситуации, когда контейнер окажется больше, чем элементы, в нём размещённые, так и наоборот - когда контейнер мал для элементов. А если знать как рассчитываются итоговые размеры, то можно избежать различных неожиданностей.