Полное руководство по Flexbox

Полное руководство по Flexbox
mangohost

Предисловие

Модуль Flexbox Layout (Flexible Box) направлен на то чтобы предоставить более эффективный способ расположения, выравнивания и распределения свободного пространства между элементами в контейнере, даже когда их размер заранее неизвестен и/или динамичен (поэтому слово "flex").

Основная идея гибкой (flex) разметки заключается в том, чтобы предоставить контейнеру возможность изменять ширину/высоту (и порядок) своих элементов, для того чтобы наилучшим образом заполнить доступное пространство (в основном для размещения на всех типах и размерах экранов). Flexbox контейнер расширяет элементы чтобы заполнить свободное пространство или сжимает их чтобы избежать переполнения.

Самое главное, что Flexbox это направленный агностик в отличии от обычных раскладок (блоков основанных на вертикальном позиционировании и строковых элементов основанных на горизонтальном позиционировании). Не смотря на то что они достаточно хорошо работают, им не хватает гибкости для поддержки больших или сложных приложений (особенно когда речь идёт об изменении ориентации, изменении размеров, растягивании, сжатии и т. д.). 

Примечание. Flexbox больше подходит для компонентов приложения и небольших макетов, тогда как CSS Grid предназначен для более масштабных макетов.

Основы и терминология

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

Если обычная система компоновки основана на блочных и строковых направлениях, то Flexbox основан на "flex-flow направлениях". Пожалуйста взгляните на этот рисунок из спецификации, объясняющий основную идею Flexbox.

Flexbox Layout

В основном элементы будут располагаться вдоль основной оси (от main-start к main-end) или попереченой оси (от cross-start к cross-end).

  • main axis - это основная ось flex-контейнера, вдоль которой расположены flex-элементы. Берегитесь того, что это не обязательно горизонтальная ось; Она зависит от свойства flex-direction;
  • main-start | main-end - flex-элементы размещаются внутри контейнера, начиная с main-start и заканчивая main-end;
  • main size - ширина или высота flex-элемента, в зависимости направления основной оси;
  • cross axis - это ось перпендикулярная основной оси, которая называется "поперечной" осью. Её направление зависит от направления основной оси;
  • cross-start | cross-end - - flex-элементы размещаются внутри контейнера, начиная с cross-start и заканчивая cross-end;
  • cross size - ширина или высота flex-элемента, в зависимости направления поперечной оси;

Поддержка браузерами

CSS Flexible Box Layout Module

IE
9
0.04%
10
0%
11
0.44%
Edge
119
0.27%
120
3.73%
121
0.52%
Firefox
120
0.23%
121
1.25%
122
0.28%
123
0%
124
0%
Chrome
119
2.45%
120
15.86%
121
1.12%
122
0.02%
123
0%
Safari
17.1
0.69%
17.2
0.85%
17.3
0.06%
17.4
0%
TP
0%
Safari on iOS
17.1
3.46%
17.2
4.68%
17.3
0.3%
Chrome for Android
121
40.53%

 

Браузер Blackberry начиная с 10 версии поддерживает новый синтаксис.

Содержание

Свойства для контейнера

Свойства для элементов

 

Свойства для родительского элемента (Flex-контейнера)

 

display

Определяет flex-контейнер; строковый или блочный зависит от переданного значения. Включает flex-контекст для всех своих прямых, дочерних элементов.

.container {
  display: flex; /* или inline-flex */
}

Обратите внимание, что CSS колонки не влияют на flex-контейнер.

flex-direction

Flex Direction

Устанавливает основную ось, таким образом определяет направление элементов расположенных в контейнере. Flexbox (помимо опциональной обёртки) представляет собой концепцию однонаправленного макета. Думайте о flex-элементах, прежде всего как горизонтальных строках или вертикальных колонках.

.container {
  flex-direction: row | row-reverse | column | column-reverse;
}
  • row (по умолчанию) -  слева направо в ltr; справа налево в rtl;
  • row-reverse - справа налево в  ltr; слева направо в  rtl;
  • column - тоже самое что row, только сверху вниз;
  • column-reverse - тоже самое что row-reverse, только снизу вверх;

flex-wrap

Flex Wrap

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

.container{
  flex-wrap: nowrap | wrap | wrap-reverse;
}
  • nowrap (по умолчанию) - все flex-элементы будут расположены на одной строке;
  • wrap - flex-элементы будут расположены на нескольких строках, сверху вниз;
  • wrap-reverse - flex-элементы будут расположены на нескольких строках, снизу вверх;

flex-flow

Это сокращение для свойств flex-direction и flex-wrap, которые вместе определяют основную и поперечные оси контейнера. По умолчанию row nowrap.

.container{
  flex-flow: <‘flex-direction’> || <‘flex-wrap’>;
}

 

justify-content

Flexbox Justify Content

Определяет выравнивание вдоль основной оси. Это помогает распределить свободное пространство, оставшееся после того как все фиксированные и не фиксированные по ширине flex-элементы достигли максимального размера. Оно также помогает осуществлять некоторый контроль над выравниванием элементов, когда они переполняют строку.

.container {
  justify-content: flex-start | flex-end | center | space-between | space-around;
}
  • flex-start (по умолчанию) - элементы прижимаются к началу строки;
  • flex-end - элементы прижимаются к концу строки;
  • center - элементы располагаются по центру вдоль строки;
  • space-between - элементы размещаются равномерно на линии; первый элемент находится в начале строки, последний элемент находится в конце строки;
  • space-around - элементы размещаются равномерно на линии с одинаковым пространством возле них. Обратите внимание, что визуально пространство не одинаковое, так как у всех элементов одинаковое пространство с обеих сторон. У первого элемента будет одна единица пространства со стороны контейнера, но две единицы между ним и следующим элементом, потому что у следующего элемента также по одной единице с двух сторон.

align-items

Flexbox Align Items

Это свойство определяет поведение flex-элементов вдоль поперечной оси на текущей строке. Думайте о нём как о justify-content, только для поперечной оси (перпендикулярной основной оси).

.container {
  align-items: flex-start | flex-end | center | baseline | stretch;
}
  • flex-start - элементы размещаются в начале поперечной оси;
  • flex-end - элементы размещаются в конце поперечной оси;
  • center - элементы располагаются по центру поперечной оси;
  • baseline - элементы выравниваются по базовой линии;
  • stretch (по умолчанию) - растягиваются чтобы заполнить весь контейнер (по-прежнему соблюдают min-width / max-width);

align-content

Flexbox Align Content

Примечание. Это свойство не действует, когда есть только одна строка flex-элементов.

.container {
  align-content: flex-start | flex-end | center | space-between | space-around | stretch;
}
  • flex-start - строки располагаются в начале контейнера;
  • flex-end - строки располагаются в конце контейнера;
  • center - строки размещаются по центру контейнера;
  • space-between - строки распределяются равномерно, первая строка располагается в начале контейнера, а последняя строка в конце;
  • space-around - строки распределяются равномерно, с одинаковым расстоянием между ними;
  • stretch (по умолчанию) - строки растягиваются по всей ширине, чтобы занять оставшееся пространство;

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

order

Flex Order

По умолчанию, все элементы располагаются в исходном для них порядке. Однако, свойство order управляет порядком, в котором располагаются элементы внутри контейнера.

.item {
  order: <integer>;
}

 

flex-grow

Flex Grow

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

Если у всех элементов свойство flex-grow установлено в 1, то свободное пространство внутри контейнера будет равномерно распределено между всеми элементами. Если у одного из элементов значение установлено в 2, то элемент будет занимать в два раза больше пространства, чем остальные (по крайней мере, попытается).

.item {
  flex-grow: <number>; /* по умолчанию 0 */
}

Нельзя указывать отрицательные числа.

flex-shrink

Это свойство определяет возможность элемента уменьшаться в размере, при необходимости.

.item {
  flex-shrink: <number>; /* по умолчанию 1 */
}

Нельзя указывать отрицательные числа.

flex-basis

Определяет размер элемента по умолчанию, до распределения оставшегося пространства. Это может быть длина (20%, 5rem и т.д.) или ключевое слово. Ключевое слово auto означает "выглядеть как моё свойство width или height". Ключевое слово content  означает что "размер основан на содержимом элемента" - это ключевое слово пока не очень хорошо поддерживается, поэтому его трудно проверить, а ещё труднее узнать что делают его братья min-content, max-content и fit-content.

.item {
  flex-basis: <length> | auto; /* по умолчанию auto */
}

Если установить значение 0, то дополнительное пространство вокруг содержимого не будет учитываться. Если установить auto, дополнительное пространство будет распределяться на основе значения flex-grow. Смотрите этот рисунок.

flex

Это сокращение для flex-grow, flex-shrink и flex-basis. Второй и третий параметры (flex-shrink и flex-basis) не обязательны. Значение по умолчанию установлено в 0 1 auto.

.item {
  flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}

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

align-self

Flexbox Align Self

Это свойство позволяет переопределить выравнивание по умолчанию (или заданное с помощью свойства align-items) для отдельных flex-элементов.

Пожалуйста посмотрите на объяснение свойства align-items, чтобы понимать доступные значения.

.item {
  align-self: auto | flex-start | flex-end | center | baseline | stretch;
}

.item {
  align-self: auto | flex-start | flex-end | center | baseline | stretch;
}

Обратите внимание, что float, clear и vertical-align не оказывают никакого влияния на flex-элемент.

Примеры

Давайте начнём с самого простого примера, решающего задачу, которая возникает почти каждый день: идеальное центрирование. Не может быть ничего проще, если вы используете Flexbox.

.parent {
  display: flex;
  height: 300px;
}

.child {
  width: 100px; 
  height: 100px;
  margin: auto;
}

Это зависит от того, что margin , установленный в auto  у flex-контейнера, поглощает дополнительное пространство. Таким образом, установка вертикального margin в auto у элемента, сделает элемент идеально центрированным по обеим осям.

Теперь давайте используем ещё несколько свойств. Рассмотрим список из 6 элементов, все с фиксированным размером в эстетическом отношении, но они могут быть автоматическими. Мы хотим, чтобы они были равномерно распределены вдоль горизонтальной оси и чтобы при изменении размера браузера всё было в порядке (без медиа-запросов!).

.flex-container {
  display: flex;
  flex-flow: row wrap;
  justify-content: space-around;
}

Готово! Всё остальное, это лишь некоторые проблемы дизайна. Ниже приведён пример на CodePen, обязательно зайдите туда и попробуйте изменить размер окон, чтобы посмотреть что произойдёт.

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

.navigation {
  display: flex;
  flex-flow: row wrap;
  justify-content: flex-end;
}

@media all and (max-width: 800px) {
  .navigation {
    justify-content: space-around;
  }
}

@media all and (max-width: 500px) {
  .navigation {
    flex-direction: column;
  }
}

Давайте попробуем сделать что-нибудь ещё лучше, играясь с гибкостью наших flex-элементов! Как насчёт трёхколоночного mobile-first макета с шапкой и футером на всю ширину экрана, и чтобы не было зависимости от исходного порядка элементов.

.wrapper {
  display: flex;
  flex-flow: row wrap;
}

.header, .main, .nav, .aside, .footer {
  flex: 1 100%;
}

@media all and (min-width: 600px) {
  .aside { flex: 1 auto; }
}

@media all and (min-width: 800px) {
  .main { flex: 2 0px; }
  .aside-1 { order: 1; }
  .main    { order: 2; }
  .aside-2 { order: 3; }
  .footer  { order: 4; }
}

Безусловно Flexbox не без ошибок. Лучшая коллекция, которую я видел представлена Philip Walton и Greg Whitworth's Flexbugs. Это Open Source место для отслеживания всех ошибок, поэтому я думаю, что лучше всего просто оставить ссылку. 

Комментарии

13 июля 2017 01:50
ergonomic.code

Нельзя делать фолбэк в виде:

div {
  display: -webkit-box; 
  display: -moz-box; 
  display: -ms-flexbox; 
  display: -webkit-flex; 
  display: flex;
}

display: -webkit-box; и display: -moz-box; не умеют flex-wrap. На этом моменте можно получить множество проблем.

13 июля 2017 17:18
Администратор

Не могу найти в статье чтобы было написано что-то про этот фолбэк. Может напишете как нужно делать?

mangohost