Ещё больше о том как работает Flexbox — объясняем на больших, красочных GIF’ках

Ещё больше о том как работает Flexbox — объясняем на больших, красочных GIF’ках
mangohost

Недавно мы начали разбираться с основными свойствами Flexbox: flex-direction, justify-content, align-items, и align-self.

Этих команд вполне достаточно для создания базовых макетов. Но как только вы начнёте разрабатывать веб-страницы с помощью Flexbox, вам необходимо будет углубиться в эту тему чтобы увеличить потенциал.

Сейчас давайте глубже рассмотрим то как Flexbox рассчитывает размеры и как мы можем использовать это для разработки адаптивных и красивых макетов.

Свойство #1: Flex-Basis

В последней статье, мы в основном рассматривали свойства, которые применяются к контейнерам. На этот раз, мы рассмотрим систему размеров, которая применяется исключительно к дочерним элементам.

Наше первое свойство, на мой взгляд одно из наименее хорошо объясняемых свойств, в руководствах по Flexbox.

Но, не волнуйтесь. Оно на самом деле довольно простое.

flex-basis управляет размером элемента по умолчанию, до того как он будет управляться другими Flexbox свойствами (об этом позже).

На GIF'ке ниже, это означает что оно взаимозаменяемо с свойством width.
Пример flex-basis

Flex-basis влияет на размер элемента относительно основной оси.

Давайте посмотрим, что происходит когда мы оставляем значение flex-basis таким же, но переключаем нашу основную ось.

 Оси Flexbox

Обратите внимание на то, что мы вручную переключили height на width. Таким образом flex-basis попеременно определяет ширину или высоту, в зависимости от flex-direction.

Свойство #2: Flex Grow

Теперь мы собираемся немного усложнить задачу.

Во первых, давайте установим для наших квадратов одинаковую ширину в 120px.

Пример flex-grow

Теперь пришло время для свойства flex-grow, значение по умолчанию у которого равно 0. Это означает, что квадратам нельзя увеличиваться в размере, чтобы занять всю ширину контейнера.

Хорошо, давайте попробуем увеличить flex-grow до 1 у каждого квадрата:

Пример flex-grow

Квадраты заняли всю ширину контейнера, а пространство между ними распределилось равномерно. Значение свойства flex-grow переопределяет значение свойства width.

Путаница в flex-grow, заключается в том, что же на самом деле означает его значение? Что на самом деле подразумевает flex-grow: 1?

Вот как выглядит flex-grow, если каждому квадрату установить значение 999:

Пример flex-grow

Это... тоже самое.

Это потому что flex-grow не абсолютное значение, а относительное.

Важно не то какое значение flex-grow квадрата само по себе, а какое оно по отношению к другим квадратам.

Если для всех квадратов мы установим значение flex-grow: 1;, а затем будем изменять это значение для Квадрата #3, то мы увидим изменения:

Пример flex-grow

Чтобы на самом деле понимать, что здесь происходит, давайте немного погрузимся в математику.

Значение flex-grow для каждого квадрата начинается с 1. Если мы сложим flex-grow каждого квадрата, то в итоге получим 6. Таким образом, контейнер разделён на 6 отдельных секций. Каждый квадрат занимает 1/6 от доступного пространства в контейнере.

Когда мы устанавливаем flex-grow: 2; для Квадрата #3, то контейнер делится на 7 различных секций, так как сумма свойств flex-grow равна 1+1+2+1+1+1.

Квадрат #3 занимает 2/7 от всего пространства, а остальные занимают по 1/7.

Когда мы устанавливаем flex-grow: 3; для Квадрата #3, контейнер делится на 8 различных секций (1 + 1 + 3 + 1 + 1 + 1) и Квадрат #3 занимает 3/8, а остальные по 1/8.

И так далее.

Flex-grow пропорционален. Если мы установим всем квадратам flex-grow: 4;, а Квадрату #3 flex-grow: 12;, то получим точно такой же результат как если бы это было 1 и 3 соответственно:

Пример flex-grow

Важно, что flex-grow для квадрата пропорционален, другим квадратам.

Ну и в качестве заключительной заметки запомните, что и как flex-basis, flex-grow применяется относительно основной оси. Наши квадраты будут  будут увеличиваться по ширине, только если мы не будем устанавливать flex-direction: column;.

Свойство #3: Flex Shrink

Flex-shrink - это противоположное свойство для flex-grow, определяющее насколько квадрат может сжиматься.

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

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

Давайте посмотрим на него в действии. Ниже на GIF'ке, у всех квадратов установлено свойство flex-grow: 1;, поэтому они занимают весь контейнер, и flex-shrink: 1;, так что они могу сжиматься.

Пример flex-shrink

Теперь давайте установим Квадрату #3 свойство flex-shrink на 0. Ему запрещено сжиматься, поэтому он увеличивается когда размер контейнера становиться больше, но не сжимается меньше установленной ширины в 120px.

Пример flex-shrink

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

Опять же, flex-shrink пропорционален. Если у одного квадрата flex-shrink: 6;, а у остальных flex-shrink: 2;, то один из квадратов будет сжиматься в 3 раза быстрее, чем остальные.

Обратите внимание на формулировку: квадрат с 3-кратным flex-shrink будет сжиматься в 3 раза быстрее. Это не означает, что он будет сжиматься на 1/3 ширины.

Свойство #4: Flex

Flex - это сокращение для grow, shrink и basis вместе взятых.

По умолчанию установлены значения в 0 (grow) 1 (shrink) и auto (basis).

Для нашего заключительного примера, давайте упростим до двух квадратов.

Вот их свойства:

.square#one {
  flex: 2 1 300px;
}
.square#two {
  flex: 1 2 300px;
}

У них одинаковый flex-basis. Это означает, что если в контейнере достаточно места для них обоих (600px контейнер плюс margin'ы и padding'и), они оба будут по 300px;

Но когда контейнер увеличивается, Квадрат #1 (у которого flex-grow выше) будет увеличиваться в 2 раза быстрее. А когда контейнер сжимается, Квадрат #2 (у которого flex-shrink выше) будет сжиматься в два раза быстрее.

Теперь всё вместе:

Пример flex

Как всё сжимается и увеличивается

Вот что может сбивать с толку, дак это когда Квадрат #1 увеличивается, он не увеличивается чтобы быть в два раза больше Квадрата #2. Точно также, когда Квадрат #2 сжимается, он не сжимается до того чтобы быть в два раза меньше Квадрата #1 - даже если пропорция flex-shrink 2 к 1.

Это не их размер который равен 2 к 1 или 1 к 2. Это их уровень сжатия и увеличения.

Немного математики

Начальный размер контейнера равен 640px. После учёта внутренних отступов 20px с каждой стороны контейнера, этого места достаточно для того чтобы flex-basis обоих квадратов вернулся в 300px.

Когда ширина контейнера устанавливается в 430px, мы теряем 210px. Квадрат #1 с flex-shrink: 1;, теряет 70px. Квадрат #2 с flex-shrink: 2;, теряет 140px;

Когда контейнер сжимается до 340px, мы теряем 300px пространства. Квадрат #1 теряет 100px, Квадрат #2 теряет 200px.

Потерянное пространство делится в соответствии с их значениями flex-shrink.

Такая же история и с flex-grow. Когда контейнер вырастает до 940px, мы получаем 300px дополнительного пространства, Квадрат #1 получается дополнительные 200px, а Квадрат #2 получает дополнительные 100px.

Когда дело доходит до flex свойств, пропорции - это название игры.

Пример flex

На GIF'ке выше вы можете увидеть как ширина регулируется в соответствии с отношениями, с дельтой (∆) показывающей разницу от flex-basis.

Заключение

В качестве финального заключения: flex-basis управляет тем насколько элемент будет большим вдоль основной оси, до того момента как происходит увеличение или сжатие. Flex-grow определяет насколько он будет увеличиваться пропорционально лежащих на одном уровне элементов, а flex-shrink определяет насколько он будет уменьшаться.

mangohost