Flexbox: уже пора!

Пара слов о поддержке Flexbox

Нынешняя спецификация flexbox не первая. В 2012 году… Впрочем, кого это волнует?
Новую спецификацию, по данным caniuse, поддерживает уже 79% браузеров. Добавим к этому поддержу с префиксами — и получим цифру 83%. Если ж учесть и частичную поддержку в Android 4.1-4.3 — то и вовсе доберемся до фантастических 94.5%! 95% браузеров, по состоянию на февраль 2020 года. Флекс поддерживает даже последняя OperaMini!

Flexbox: инструкция по применению

Для начала: что стоит знать?

В первую очередь, нужно указать родителю display: flex или display: inline-flex. Различие между ними такое же, как и между block и inline-block или между table и inline-table, так что останавливаться на этом не будем.

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

Свойства родительского контейнера

Свойство flex-direction (направление оси)

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

Значения:

  • row (по умолчанию) — привычно, слева на право
  • column — столбиком
  • row-reverse — по-арабски, справа налево
  • column-reverse — по-идиотски, снизу вверх

Свойство justify-content (выравнивание по главной оси)

Определяет выравнивание дочерних элементов по главной оси. Стоит обратить внимание, что это свойство не всегда отвечает за выравнивание элементов по горизонтали. Оно отвечает именно за главную ось. По умолчанию главная ось является горизонтальной, но если вы задали свойство flex-direction: column, то главная ось станет вертикальной.

Значения:

  • flex-start (по умолчанию) — начало родительского блока
  • flex-end — конец родительского блока
  • center — центр родительского блока

И вот тут начинается самое интересное

  • space-between — первый дочерний элемент — в начале, последний — в конце. Остальные расположены так, чтобы между ними было одинаковое расстояние
  • space-around — все тоже самое, но перед первым и после последнего элементов также есть отступы, которые равны отступам между элементами

Свойство align-items (выравнивание по поперечной оси)

Дождались! Свойство, которое позволяет забыть о геморрое с vertical-align: center и top: 50%/transform: translateY(-50%).
Как и в предыдущем свойстве, не стоит забывать, что оно отвечает за выравнивание по поперечной оси, которая, в зависимости от значения flex-direction, может идти по вертикали или по горизонтали.

Уже знакомые нам значения:

  • flex-start — прижатие к началу
  • flex-end — прижатие к концу
  • center — по центру

А также парочка других, на замену space-between и space-around:

  • baseline — выравнивание по базовой линии
  • stretch (по умолчанию) — растягивает на 100%

Свойство flex-wrap (одно- или многоколоночность)

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

Значения:

  • nowrap (по умолчанию) — одна строка/колонка (в зависимости от значения flex-direction). Все дочерние блоки сжимаются.
  • wrap — многоколоночность. То что не влезло переносится на новую строку или в новую колонку
  • wrap-reverse — тоже, только наоборот: элементы идут в обратном порядке

Свойство align-content (небольшое дежавю)

Данное свойство выравнивает строки/колонки, которые образовались в результате использования flex-wrap: wrap/wrap-reverse.

Значения:

  • flex-start
  • flex-end
  • center
  • space-between
  • space-around
  • stretch (по умолчанию)

Описывать их не буду, они распределяют элементы так же, как и одноименные значения в justify-content/align-items.

Свойства дочерних элементов

flex-basis (размер элемента)

Значение по умолчанию: auto.

По-моему личному мнению, наименее востребованное свойство. Указывает размер элемента по главной оси (в любых единицах измерения).

flex-grow (расширяемость элемента)

Значение по умолчанию: 0 (не забирает себе ни одну часть свободного места).

Указывает сколько долей свободного места элемент может забрать себе.

Пример 1:
Родитель — ширина 1000px,
Элемент-1 — flex-grow: 1,
Элемент-2 — flex-grow: 3.
Стало быть элемент-1 будет иметь длину 1000/(1+3)*1=250px, а элемент-2 — оставшиеся 750px.

Пример 2:
Условия те же, но у обоих элементов указана ширина — 100px.
В таком случае элемент-1 будет иметь ширину (1000-(100+100))/(1+3)*1+100=300px, а элемент-2 — 700px.
Что означают эти вычисления? Для начала мы узнали количество оставшегося места (1000-(100+100)=800), затем разделили на общее количество долей(800/(3+1)=200), и наконец отдали первому элементу его долю + 100px, которые были у него изначально (200*1+100=300).

flex-shrink (сжимаемость элемента)

Значение по умолчанию: 1 (уменьшается одинаково с другими элементами).

Аналогичное свойство, но работающее в обратном направлении. Указывает пропорцию уменьшения блока, по отношению у другим элементам.

Пример 1:
Родитель — 1000px,
Элемент-1 — flex-shirk: 0,
Элемент-2 — flex-shrink: 1,
У обоих элементов указана ширина 650px.
Что произойдет? Первому элементу указано свойство flex-shrink: 0 т.е. ему запрещено уменьшаться. Значит это придется сделать второму элементу. В итоге ширина элемента-1 будет равна 650px, а элемента-2 — 350px.

Пример 2:
Элемент-1 — flex-shrink: 1,
Элемент-2 — flex-shrink: 2,
Остальные условия те же.
Как вы, возможно, уже догадались, ширина первого блока составит 550px, а второго — 450px. Но давайте всё таки проследим за тем, что произошло:
Для начала определяется количество недостающего места (650+650-1000=300), затем вычисляется размер одной доли flex-shrink (300/(1+2)=100) и, наконец, из каждого элемента вычитается указанная в его стилях доля (650-100*1=550px и 650-100*2=450px).

align-self (выравнивание отдельного элемента по поперечной оси)

Указывает расположение по поперечной оси отдельно взятого элемента. Можно контейнеру указать align-items: flex-start и несколько элементов отправить, например в конец, приписав им align-self: flex-end.

Значения те же, что и у align-items:

  • flex-start
  • flex-end
  • center
  • baseline
  • stretch

order (порядок элемента)

Свойство, с помощью которого можно творить чудеса. Указывает каким номером будет идти элемент. Можно сортировать элементы, прописывая им это свойство.

John Doe:
"но если вы задали свойство flex-direcrtion: row, то главная ось станет вертикальной" — ошибочка
Бобр Добр:
John Doe, column, разумеется. Спасибо, поправил.