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

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

  • 22 марта, 2023
  • читать 15 мин

Модуль Flexbox-лейаута (flexible box — «гибкий блок», на данный момент W3C Candidate Recommendation) ставит задачу предложить более эффективный способ вёрстки, выравнивания и распределения свободного места между элементами в контейнере, даже когда их размер неизвестен и/или динамический (отсюда слово «гибкий»).

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

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

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

Основы

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

Если обычный лейаут основывается на направлениях потоков блочных и инлайн-элементов, то flex-лейаут основывается на «направлениях flex-потока». Ознакомьтесь с этой схемой из спецификации, разъясняющей основную идею flex-лейаутов.

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

  • main-axis — главная ось, вдоль которой располагаются 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-элемента в зависимости от выбранной размерности равняется этой величине. Это свойство совпадает с width или height элемента в зависимости от выбранной размерности.

Свойства

display: flex | inline-flex;

Применяется к: родительскому элементу flex-контейнера.

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

display: other values | flex | inline-flex;

Имейте в виду:

  • CSS-столбцы columns не работают с flex-контейнером
  • float, clear и vertical-align не работают с flex-элементами

flex-direction

Применяется к: родительскому элементу flex-контейнера.

Устанавливает главную ось main-axis, определяя тем самым направление для flex-элементов, размещаемых в контейнере.

flex-direction: row | row-reverse | column | column-reverse

  • row (по умолчанию): слева направо для ltr, справа налево для rtl;
  • row-reverse: справа налево для ltr, слева направо для rtl;
  • column: аналогично row, сверху вниз;
  • column-reverse: аналогично row-reverse, снизу вверх.

flex-wrap

Применяется к: родительскому элементу flex-контейнера.

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

flex-wrap: nowrap | wrap | wrap-reverse

  • nowrap (по умолчанию): однострочный / слева направо для ltr, справа налево для rtl;
  • wrap: многострочный / слева направо для ltr, справа налево для rtl;
  • wrap-reverse: многострочный / справа налево для ltr, слева направо для rtl.

flex-flow

Применяется к: родительскому элементу flex-контейнера.

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

flex-flow: <'flex-direction'> || <'flex-wrap'>

justify-content

Применяется к: родительскому элементу flex-контейнера.

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

justify-content: flex-start | flex-end | center | space-between | space-around

  • flex-start (по умолчанию): элементы сдвигаются к началу строки;
  • flex-end: элементы сдвигаются к концу строки;
  • center: элементы выравниваются по центру строки;
  • space-between: элементы распределяются равномерно (первый элемент в начале строки, последний — в конце);
  • space-around: элементы распределяются равномерно с равным расстоянием между собой и границами строки.

align-items

Применяется к: родительскому элементу flex-контейнера.

Определяет поведение по умолчанию для того, как flex-элементы располагаются относительно поперечной оси на текущей строке. Считайте это версией justify-content для поперечной оси (перпендикулярной к основной).

align-items: flex-start | flex-end | center | baseline | stretch

  • flex-start: граница cross-start для элементов располагается на позиции cross-start;
  • flex-end: граница cross-end для элементов располагается на позиции cross-end;
  • center: элементы выравниваются по центру поперечной оси;
  • baseline: элементы выравниваются по своей базовой линии;
  • stretch (по умолчанию): элементы растягиваются, заполняя контейнер (с учётом min-width/max-width).

align-content

Применяется к: родительскому элементу flex-контейнера.

Выравнивает строки flex-контейнера при наличии свободного места на поперечной оси аналогично тому, как это делает justify-content на главной оси.

Замечание: это свойство не работает с однострочным flexbox.

align-content: flex-start | flex-end | center | space-between | space-around | stretch

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

order

Применяется к: дочернему элементу / flex-элементу.

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

order: <integer>

flex-grow

Применяется к: дочернему элементу / flex-элементу.

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

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

flex-grow: <number> (по умолчанию 0)

Отрицательные числа не принимаются.

flex-shrink

Применяется к: дочернему элементу / flex-элементу.

Определяет для flex-элемента возможность сжиматься при необходимости.

flex-shrink: <number> (<b>default</b> 1)

Отрицательные числа не принимаются.

flex-basis

Применяется к: дочернему элементу / flex-элементу.

Определяет размер по умолчанию для элемента перед распределением пространства в контейнере.

flex-basis: <length> | auto (default auto)

flex

Применяется к: дочернему элементу / flex-элементу.

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

flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]

align-self

Применяется к: дочернему элементу / flex-элементу.

Позволяет переопределить выравнивание, заданное по умолчанию или в align-items, для отдельных flex-элементов.

Обратитесь к описанию свойства align-items для лучшего понимания доступных значений.

align-self: auto | flex-start | flex-end | center | baseline | stretch

Примеры

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

.parent {
  display: flex;
  height: 300px; /* Або що завгодно */
}

.child {
  width: 100px;  /* Або що завгодно */
  height: 100px; /* Або що завгодно */
  margin: auto;  /* Магія! */
}

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

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

.flex-container {
  /* Спочатку створимо flex-контекст */
  display: flex;
  
  /* Тепер визначимо напрямок потоку і чи хочемо ми, щоб елементи
   переносилися на новий рядок
   * Пам'ятайте, що це так само, як і:
   * flex-direction: row;
   * flex-wrap: wrap;
   */
  flex-flow: row wrap;
  
  /* Тепер визначимо, як розподілятиметься простір */
  justify-content: space-around;
}

Готово. Всё остальное — уже дело оформления.

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

/* Великі екрани */
.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-элементов! Как насчёт ориентированного на мобильные устройства трёхколоночного макета с полноширинной шапкой и подвалом? И другим порядком расположения.

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

/* Задаємо всім елементам ширину 100% */
.header, .main, .nav, .aside, .footer {
  flex: 1 100%;
}

/* У цьому випадку ми покладаємось на вихідний порядок для орієнтації на
 * мобільні пристрої:
 * 1. header
 * 2. nav
 * 3. main
 * 4. aside
 * 5. footer
 */

/* Екрани середнього розміру */
@media all and (min-width: 600px) {
  /* Обидва сайдбари розташовуються в одному рядку */
  .aside { flex: 1 auto; }
}

/* Великі екрани */
@media all and (min-width: 800px) {
  /* Ми міняємо місцями елементи .aside-1 та .main, а також повідомляємо
   * елементу .main забирати вдвічі більше місця, ніж сайдбари.
   */
  .main { flex: 2 0px; }
  
  .aside-1 { order: 1; }
  .main    { order: 2; }
  .aside-2 { order: 3; }
  .footer  { order: 4; }
}

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

  • (modern) означает поддержку нового синтаксиса из спецификации (display: flex;)
  • (hybrid) означает поддержку старого неофициального синтаксиса из 2011 (display: flexbox;)
  • (old) означает поддержку старого синтаксиса из 2009 (display: box;)
ChromeSafariFirefoxOperaIEAndroidiOS
21+ (modern)
20- (old)
3.1+ (old)2-21 (old)
22+ (new)
12.1+ (modern)10+ (hybrid)2.1+ (old)3.2+ (old)

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

Для более подробной информации о том, как и когда использовать различные синтаксисы для обеспечения лучшей поддержки браузерами, обратитесь к этой статье (CSS-Tricks) или этой статье (DevOpera).

SASS-@mixin для облегчения боли:

@mixin flexbox() {
  display: -webkit-box;
  display: -moz-box;
  display: -ms-flexbox;
  display: -webkit-flex;
  display: flex;
}

@mixin flex($values) {
  -webkit-box-flex: $values;
  -moz-box-flex:  $values;
  -webkit-flex:  $values;
  -ms-flex:  $values;
  flex:  $values;
}

@mixin order($val) {
  -webkit-box-ordinal-group: $val;  
  -moz-box-ordinal-group: $val;     
  -ms-flex-order: $val;     
  -webkit-order: $val;  
  order: $val;
}

.wrapper {
  @include flexbox();
}

.item {
  @include flex(1 200px);
  @include order(2);
}

Нажимай и выигрывай от
1 000 до 5 000 ₴