Как работает CSS Flexbox

7215

Как работает CSS Flexbox

CSS flexbox (Flexible Box Layout Module) — модуль макета гибкого контейнера — представляет собой способ компоновки элементов, в основе лежит идея оси.

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

Модуль flexbox позволяет решать следующие задачи:

  • Располагать элементы в одном из четырех направлений: слева направо, справа налево, сверху вниз или снизу вверх.
  • Переопределять порядок отображения элементов.
  • Автоматически определять размеры элементов таким образом, чтобы они вписывались в доступное пространство.
  • Решать проблему с горизонтальным и вертикальным центрированием.
  • Переносить элементы внутри контейнера, не допуская его переполнения.
  • Создавать колонки одинаковой высоты.
  • Создавать прижатый к низу страницы подвал сайта.

Flexbox решает специфические задачи — создание одномерных макетов, например, навигационной панели, так как flex-элементы можно размещать только по одной из осей.

Основные понятия

Как работает CSS Flexbox
Как работает CSS Flexbox

Для описания модуля Flexbox используется определенный набор терминов. Значение flex-flow и режим записи определяют соответствие этих терминов физическим направлениям: верх / право / низ / лево, осям: вертикальная / горизонтальная и размерам: ширина / высота.

Главная ось (main axis) — ось, вдоль которой выкладываются flex-элементы. Она простирается в основном измерении.

Main start и main end — линии, которые определяют начальную и конечную стороны flex-контейнера, относительно которых выкладываются flex-элементы (начиная с main start по направлению к main end).

Основной размер (main size) — ширина или высота flex-контейнера или flex-элементов, в зависимости от того, что из них находится в основном измерении, определяют основной размер flex-контейнера или flex-элемента.

Поперечная ось (cross axis) — ось, перпендикулярная главной оси. Она простирается в поперечном измерении.

Cross start и cross end — линии, которые определяют начальную и конечную стороны поперечной оси, относительно которых выкладываются flex-элементы.

Поперечный размер (cross size) — ширина или высота flex-контейнера или flex-элементов, в зависимости от того, что находится в поперечном измерении, являются их поперечным размером.

Flex-контейнер

Flex-контейнер устанавливает новый гибкий контекст форматирования для его содержимого. Flex-контейнер не является блочным контейнером, поэтому для дочерних элементов не работают такие CSS-свойства, как floatclearvertical-align. Также, на flex-контейнер не оказывают влияние свойства column-*, создающие колонки в тексте и псевдоэлементы ::first-line и ::first-letter.

Модель flexbox-разметки связана с определенным значением CSS-свойства display родительского html-элемента, содержащего внутри себя дочерние блоки. Для управления элементами с помощью этой модели нужно установить свойство display следующим образом:

.flex-container {
/*генерирует flex-контейнер уровня блока*/
display: -webkit-flex; 
display: flex; 
}

.flex-container {
/*генерирует flex-контейнер уровня строки*/
 display: -webkit-inline-flex;
 display: inline-flex; 
}

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

Если родительский блок содержит текст или изображения без оберток, они становятся анонимными flex-элементами. Текст выравнивается по верхнему краю блока-контейнера, а высота изображения становится равной высоте блока, т.е. оно деформируется.

Flex-элементы

Flex-элементы — блоки, представляющие содержимое flex-контейнера в потоке. Flex-контейнер устанавливает новый контекст форматирования для своего содержимого, который обуславливает следующие особенности:

  • Для flex-элементов блокируется их значение свойства display. Значение display: inline-block; и display: table-cell; вычисляется в display: block;.
  • Пустое пространство между элементами исчезает: оно не становится своим собственным flex-элементом, даже если межэлементный текст обернут в анонимный flex-элемент. Для содержимого анонимного flex-элемента невозможно задать собственные стили, но оно будет наследовать их (например, параметры шрифта) от flex-контейнера.
  • Абсолютно позиционированный flex-элемент не участвует в компоновке гибкого макета.
  • Поля margin соседних flex-элементов не схлопываются.
  • Процентные значения margin и padding вычисляются от внутреннего размера содержащего их блока.
  • margin: auto; расширяются, поглощая дополнительное пространство в соответствующем измерении. Их можно использовать для выравнивания или раздвигания смежных flex-элементов.
  • Автоматический минимальный размер flex-элементов по умолчанию является минимальным размером его содержимого, то есть min-width: auto;. Для контейнеров с прокруткой автоматический минимальный размер обычно равен нулю.

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

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

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

Display: Flex

Вот пример страницы:

У нас есть 4 разноцветных div’а разных размеров, которые находятся внутри серого div’а. У каждого div’а есть свойство display: black. Поэтому каждый квадрат занимает всю ширину строки.

Чтобы начать работать с Flexbox, нам нужно сделать наш контейнер flex-контейнером. Делается это так:

#container {
  display: flex;
}

Вроде бы ничего особо и не изменилось — div’ы всего лишь встали в ряд. Но вы сделали что-то действительно мощное. Вы дали вашим квадратам классное свойство, называемое “flex-контекст”.

Flex Direction

У flex-контейнера есть две оси: главная ось и перпендикулярная ей.

По умолчанию все предметы располагаются вдоль главной оси: слева направо. Поэтому наши квадраты выровнялись в линию, когда мы применили display: flex. Однако flex — direction позволяет вращать главную ось.

#container {
  display: flex;
  flex-direction: column;
}

Justify Content

Justify-content отвечает за выравнивание элементов по главной оси/

Вернемся к flex-directional: row.

#container {
  display: flex;
  flex-direction: row;
  justify-content: flex-start;
}

Justify-content может принимать 5 значений:

  1. flex-start;
  2. flex-end;
  3. center;
  4. space-between;
  5. space-around.

Space-between задает одинаковое расстояние между квадратами, но не между контейнером и квадратами. Space-around также задает одинаковое расстояние между квадратами, но теперь расстояние между контейнером и квадратами равно половине расстояния между квадратами.

Align Self

Align-self позволяет выравнивать элементы по отдельности.

#container {
  align-items: flex-start;
}

.square#one {
  align-self: center;
}

// Only this square will be centered.

Давайте для двух квадратов применим align-self, а для остальных применим align-items: center и flex-directional: row.

Flex Grow

Это свойство немного сложнее.

Для начала давайте зададим нашим квадратикам одинаковую ширину в 120px:

По умолчанию значение flex — grow равно 0. Это значит, что квадратам запрещено расти (занимать оставшееся место в контейнере).

Попробуем задать flex-grow равным 1 для каждого квадрата:

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

Но здесь возникает один вопрос: что значит flex-grow: 1?

Попробуем задать flex-grow равным 999:

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

Это значит, что не важно, какое значение у flex-grow, важно, какое оно по отношению к другим квадратам:

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

Когда flex-grow третьего квадрата становится равным 2, контейнер делится на 7 частей (1 + 1 + 2 + 1 + 1 + 1).

Теперь третий квадрат занимает 2/7 пространства, остальные — по 1/7.

И так далее.

Стоит помнить, что flex-grow работает только для главной оси (пока мы не поменяем ее направление).

Заключение

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

источник