Как изменить направление flex

В этой статье познакомимся с технологией CSS Flexbox, предназначенной для создания гибких макетов веб-страниц

В этой статье познакомимся с технологией CSS Flexbox, предназначенной для создания гибких макетов веб-страниц.

CSS - Flexbox верстка

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

CSS Flexbox позволяет создать адаптивный дизайн намного проще, чем с использованием Float и позиционирования.

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

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

CSS Flexbox поддерживается всеми используемые на сегодняшний момент современными браузерами (с использованием префиксов: IE10+, Edge12+, Firefox 2+, Chrome 4+, Safari 3.1+, Opera 12.1+, iOS Safari 3.2, Opera mini, Android 2.1+, Blackberry 7+).

Основы CSS Flexbox

Создание CSS разметки с помощью Flexbox начинается с установки необходимому HTML элементу CSS-свойства display со значением flex или flex-inline.

После этого данный элемент становится flex-контейнером, а все его непосредственные дочерние элементы – flex-элементами. При этом когда мы говорим о flexbox то подразумеваем под этим только элемент с display:flex или display:flex-inline и все элементы непосредственно расположенные в нём. Таким образом в CSS Flexbox имеется всего два типа элементов: flex-контейнер и flex-элемент.

<style>
.flex-container {
  display: flex; /* flex || inline-flex */
}
<style>

<!-- flex-контейнер -->
<div class="flex-container">
  <div>flex-элемент #1</div>
  <div>flex-элемент #2</div>
  <div>flex-элемент #3</div>
</div>

Элементы CSS Flexbox

По умолчанию flex-элементы во flex-контейнере занимают всю его высоту.

Значение flex или flex-inline определяет то, как flex-контейнер будет представлен на странице. Если его необходимо отобразить в виде блока, то используйте значение flex. Если элемент необходимо представить как строку, то используйте значение flex-inline. В этом случае он будет занимать столько места странице, сколько необходимо для отображения его элементов.

Устройство flex-контейнера. Направление осей

На рисунке представлена схема устройства flex-контейнера:

Схема устройства flex-контейнера в CSS flexbox. Направление осей

Направление расположение flex-элементы в flex-контейнере определяется посредством осей.

В CSS Flexbox имеются две оси. Первая ось называется главной (по умолчанию она направлена слева направо). Вторая — поперечная (по умолчанию направлена сверху вниз), она всегда перпендикулярно главной. Главная ось задаёт основное направление flex-элементов во flex-контейнере, а поперечная ось определяет их направление при переносе на новую линию.

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

Направление главной оси можно изменить, осуществляется это с помощью CSS-свойства flex-direction.

flex-direction: row;
/* row (слева направо) - по умолчанию
    row-reverse (справа налево)
    column (сверху вниз)
    column-reverse (снизу вверх) */

С помощью этого свойства можно сделать так, чтобы flex-элементы располагались не рядами (rows), а колонками (columns). Осуществляется это с помощью значения column или column-reverse.

Расположение flex-элементов в CSS Flexbox при установке flex-контейнеру свойства flex-direction со значением column

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

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

Но это можно изменить. Разрешить перенос flex-элементов на новые линии осуществляется с помощью установки flex-контейнеру CSS свойства flex-wrap со значением wrap или wrap-reverse.

flex-wrap: wrap;
/* nowrap (только на одной линии - по умолчанию)
    wrap (разрешить перенос flex-элементов на новые линии)
    wrap-reverse (осуществлять перенос flex-элементов в обратном порядке) */

Flex-сетка в которой разрешён перенос flex-элементов на новые линии

Значения wrap и wrap-reverse CSS-свойства flex-wrap определяют направление поперечной оси.

Свойства flex-direction и flex-wrap можно указать с помощью универсального CSS свойства flex-flow:

flex-flow: row nowrap; /* 1 значение - flex-direction, 2 значение - flex-wrap */

Выравнивание flex-элементов

Во Flexbox выравнивание элементов внутри контейнера осуществляется по двум направлениям (осям).

Выравнивание flex-элементов по направлению главной оси

Выравнивание элементов вдоль основной оси осуществляется с помощью CSS свойства justify-content:

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

Способы выравнивания flex-элементов вдоль направления главной оси

Выравнивание flex-элементов вдоль поперечной оси

Выравнивание flex-элементов во flex-контейнере по направлению поперечной оси осуществляется с помощью CSS-свойства align-items:

align-items: stretch;
/* stretch (растягиваются по всей длине линии вдоль направления поперечной оси) – по умолчанию
    flex-start (располагаются относительно начала поперечной оси)
    flex-end (относительно конца поперечной оси)
    baseline (относительно базовой линии)
    center (по центру) */

Способы выравнивания flex-элементов вдоль направления поперечной оси

Выравнивание линий flex-контейнера

CSS Flexbox позволяет выравнивать не только сами flex-элементы, но и линии на которых они расположены.

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

CSS Flexbox. Способы выравнивания линий во flex-контейнере

Свойство align-content имеет смысл использовать только тогда, когда flex-элементы во flex-контейнере располагаются на нескольких линиях. Чтобы это произошло, необходимо, во-первых, чтобы ширина всех flex-элементов была больше ширины flex-контейнера, а во-вторых flex-контейнер должен иметь в качестве CSS-свойства flex-wrap значение wrap или wrap-reverse.

CSS-свойство align-self

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

align-items: stretch; /* auto (по умолчанию) || stretch || flex-start || flex-end || baseline || center */

Пример:

<div class="flex-container">
  <div class="flex-container_element-1">
    1
  </div>
  <div class="flex-container_element-2">
    2
  </div>
  <div class="flex-container_element-3">
    3
  </div>
  <div class="flex-container_element-4">
    4
  </div>
</div>

CSS:

.flex-container {
  display: flex;
  width: 300px;
  height: 150px;
  align-items: center;
  padding: 10px;
  background-color: #efefef;
}
.flex-container_element-1,
.flex-container_element-2,
.flex-container_element-3,
.flex-container_element-4 {
  flex-basis: 70px;
  text-align: center;
  padding: 15px;
  font-size: 30px;
}
.flex-container_element-1 {
  align-self: flex-start;
  background: #fe4;
}
.flex-container_element-2 {
  align-self: flex-end;
  background: pink;
}
.flex-container_element-3 {
  align-self: stretch;
  background: lime;
}
.flex-container_element-4 {
  align-self: auto;
  background: cyan;
}

Как работает CSS свойство align-self

Изменение порядка следования flex-элементов

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

order: 0;
/*
  0 (по умолчанию)
  целое положительное или отрицательное число
*/

Например:

<div class="flex-container">
  <div class="flex-container_element-1">...</div>
  <div class="flex-container_element-2">...</div>
  <div class="flex-container_element-3">...</div>
  <div class="flex-container_element-4">...</div>
</div>
CSS:
.flex-container {
  display: flex;
}
/* переместим 2 flex-элемент в конец */
.flex-container_element-2 {
  order: 2;
}
/* передвинем 3 элемент до 2 */
.flex-container_element-3 {
  order: 1;
}
/* расположим 4 flex-элемент до 1 */
.flex-container_element-4 {
  order: -1;
}

Flexbox - Как работает CSS свойство order

Управление шириной flex-элемента

Во Flexbox есть несколько CSS свойств, определяющих то, какая ширина может быть у flex-элемента.

CSS-свойство flex-basis

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

Конечная ширина flex-элемента будет определяться в зависимости от значений CSS-свойств flex-grow и flex-shrink, которые установлены не только для этого элемента, но и для других flex-элементов этого flex-контейнера.

CSS-свойство flex-grow

Это свойство определяет, может ли начальная ширина flex-элемента увеличиваться (расти). Увеличение ширины flex-элемента осуществляется за счёт свободного пространства линии. В качестве значения CSS-свойства flex-grow указывается целое число. Именно это значение и определяет (если оно больше или равно 1) какую часть свободного пространства flex-элемент заберёт себе.

Например:

<div class="flex-container">
  <div class="flex-container_element-1">...</div>
  <div class="flex-container_element-2">...</div>
</div>
CSS:
.flex-container {
  display: flex;
  width: 600px;
}
.flex-container_element-1 {
  flex-basis: 40%;
  flex-grow: 1;
}
.flex-container_element-2 {
  flex-basis: 40%;
  flex-grow: 4;
}

Как работает CSS свойство flex-grow

В этом примере, если flex-элементы расположены на одной линии и в ней есть свободное пространство (600×(1-0,8)=120px):

  • к ширине элемента .flex-container_element-1 добавится 1/5 часть этого пространства (120×1/5=24px);
  • к ширине элемента .flex-container_element-2 добавится 4/5 части этого пространства (120×4/5=96px).

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

По умолчанию CSS свойство flex-grow имеет значение 0. Это означает, что flex-элемент не может расти (увеличивать свою ширину).

CSS-свойство flex-shrink

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

Например:

<div class="flex-container">
  <div class="flex-container_element-1">...</div>
  <div class="flex-container_element-2">...</div>
</div>
CSS:
.flex-container {
  display: flex;
  width: 500px;
}
.flex-container_element-1 {
  flex-basis: 300px;
  flex-shrink: 1;
}
.flex-container_element-2 {
  flex-basis: 300px;
  flex-shrink: 3;
}

Как работает CSS свойство flex-shrink

Ширина flex-контейнера 500px. Для отображения flex-элементов необходимо 600px. В итоге не хватает 100px. В этом примере уменьшаться могут 2 flex-элемента (.flex-container_element-1 и .flex-container_element-2). Ширина первого flex-элемента .flex-container_element-1 в данном случае составит 300 – 1/4*100= 275px. Ширина второго flex-элемента .flex-container_element-2 в данном случае составит 300 – 3/4*100= 225px.

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

flex-shrink: 1;

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

CSS-свойство flex

Для удобной установки flex-grow, flex-shrink и flex-basis можно использовать CSS свойство flex.

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

flex: 0 1 auto;
/*
  0 - flex-grow (1 значение)
  1 - flex-shrink (2 значение)
  auto - flex-basis (3 значение)
*/

Пример верстки макета на CSS Flexbox

В этом разделе создадим простой адаптивный макет всей страницы на CSS Flexbox.

Структура макета будет состоять из 3 секций:

  • header (для вывода заголовка и основного меню);
  • main (для отображения основной части);
  • footer (для футера).

Основную часть (main) в свою очередь разделим ещё на 2 раздела (их позиционирование будем осуществлять с помощью CSS Flexbox). На больших экранах (>=992px) эти разделы выстроим горизонтально, а на остальных — вертикально (<992px).

<style>
  /* контейнер */
  .container {
    width: 100%;
    max-width: 1200px;
    padding-right: 15px;
    padding-left: 15px;
    margin-left: auto;
    margin-right: auto;
  }

  /* flex-контейнер */
  .row {
    display: -ms-flexbox;
    display: flex;
    -ms-flex-wrap: wrap;
    flex-wrap: wrap;
    margin-right: -15px;
    margin-left: -15px;
  }

  /* общие настройки для flex-элементов */
  .col {
    position: relative;
    width: 100%;
    padding-right: 15px;
    padding-left: 15px;
  }

  /* ширина блоков .col__article и .col__aside по умолчанию */
  .col__article,
  .col__aside {
    -ms-flex: 0 0 100%;
    flex: 0 0 100%;
    max-width: 100%;
  }

  /* ширина блоков .col__article и .col__aside для больших экранов */
  @media (min-width: 992px) {
    /* 2/3 от ширины контейнера */
    .col__article {
      -ms-flex: 0 0 66.666667%;
      flex: 0 0 66.666667%;
      max-width: 66.666667%;
    }

    /* 1/3 от ширины контейнера */
    .col__aside {
      -ms-flex: 0 0 33.333333%;
      flex: 0 0 33.333333%;
      max-width: 33.333333%;
    }
  }
</style>

<header class="container">
  <!-- Шапка страницы -->
</header>
<main class="container">
  <div class="row">
    <article class="col col__article">
      <!-- Основная часть -->
    </article>
    <aside class="col col__aside">
      <!-- Боковая область -->
    </aside>
  </div>
</main>
<footer class="container">
  <!-- Футер -->
</footer>

Макет веб-страницы, созданный с использованием CSS Flexbox

В CSS для поддержки макета большинством браузеров добавлены свойства с префиксами и max-width.

Для «превращения» блока во flex-контейнер используется класс row. Установку ширины flex-элементам .col__article и .col__aside внутри flex-контейнера выполнено с использованием CSS-свойства flex.

В качестве примера разметим посредством flexbox ещё футер и создадим в элементе .col__article блок состоящий из трёх элементов (минимальная ширина одного элемента — 300px). В футере разместим четыре блока (минимальная ширина одного блока — 200px).

<style>
  /* ... */
  .col__other-article {
    -ms-flex: 1 0 0;
    flex: 1 0 0;
    min-width: 300px;
  }

  .col__footer {
    -ms-flex: 1 0 0;
    flex: 1 0 0;
    min-width: 200px;
  }
</style>

<header class="container">
  <!-- Шапка страницы -->
</header>
<main class="container">
  <div class="row">
    <article class="col col__article">
      <!-- Основная часть -->
      <div class="row">
        <div class="col col__other-article">
          <!-- Ещё 1 -->
        </div>
        <div class="col col__other-article" style="padding-bottom: 15px;">
          <!-- Ещё 2 -->
        </div>
        <div class="col col__other-article" style="padding-bottom: 15px;">
          <!-- Ещё 3 -->
        </div>
      </div>
    </article>
    <aside class="col col__aside">
      <!-- Боковая область -->
    </aside>
  </div>
</main>
<footer class="container">
  <div class="row">
    <div class="col col__footer">
      <!-- Секция футера 1 -->
    </div>
  </div>
  <div class="row">
    <div class="col col__footer">
      <!-- Секция футера 2 -->
    </div>
  </div>
  <div class="row">
    <div class="col col__footer">
      <!-- Секция футера 3 -->
    </div>
  </div>
  <div class="row">
    <div class="col col__footer">
      <!-- Секция футера 4 -->
    </div>
  </div>
</footer>

Верстка макета страницы на CSS Flexbox

CSS модуль раскладки Flexible Box, обычно называемый флексбокс или flexbox или просто flex (флекс), был разработан как модель одномерного-направленного макета и как один из методов распределения пространства между элементами в интерфейсе, с мощными возможностями выравнивания. В этой статье даётся краткое описание основных функций flexbox, которые мы рассмотрим более подробно в остальных руководствах.

Когда мы описываем flexbox как одномерно-направленный, мы имеем в виду, что flexbox имеет дело с макетом в одной плоскости за раз – либо в виде строки, либо в виде столбца. Как альтернативу можно упомянуть двумерную модель CSS Grid Layout, которая управляет и столбцами и строками одновременно.

Flexbox: две оси

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

Главная ось

Главная ось определяется свойством flex-direction, которая может принимать одно из следующих значений:

  • row
  • row-reverse
  • column
  • column-reverse

Если вы выберете row или row-reverse, ваша главная ось будет проходить в горизонтальном направлении (inline direction).

If flex-direction is set to row the main axis runs along the row in the inline direction.

Если вы выберете column или column-reverse, ваша главная ось будет проходить в вертикальном направлении (block direction).

If flex-direction is set to column the main axis runs in the block direction.

Побочная ось

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

If flex-direction is set to row then the cross axis runs in the block direction.

Если свойство flex-direction задано как column или column-reverse, побочная ось будет проходить в горизонтальном направлении.

If flex-direction is set to column then the cross axis runs in the inline direction.

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

Начало и конец строки

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

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

Если свойству flex-direction задано значение row и вы работаете с английским языком, то начало главной оси будет слева, а конец главной оси – справа.

Working in English the start edge is on the left.

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

The start edge in a RTL language is on the right.

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

Спустя некоторое время становится естественным думать о начале и конце оси, а не о левом и правом краях. Это будет полезно для вас при работе с другими методами, такими как CSS Grid Layout, которые следуют тем же шаблонам.

Flex контейнер

Область документа, использующая flexbox, называется flex контейнером. Чтобы создать flex контейнер, мы задаём значение flex или inline-flex для свойства display контейнера. Как только мы делаем это, прямые потомки этого контейнера становятся flex элементами. Как и для всех свойств в CSS, некоторые начальные значения уже определены, поэтому при создании flex-контейнера все содержащиеся в нем flex-элементы будут вести себя следующим образом.

  • Элементы отображаются в ряд (свойство flex-direction по умолчанию имеет значение row).
  • Позиционирование элементов начинается от начала главной оси.
  • Элементы не растягиваются по основной оси, но могут сжиматься.
  • Элементы будут растягиваться, чтобы заполнить размер побочной оси.
  • Свойству flex-basis задано значение auto.
  • Свойству flex-wrap задано значение nowrap.

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

Вы можете увидеть принцип работы в живом примере ниже. Попробуйте отредактировать или добавить дополнительные элементы, чтобы проверить поведение flexbox.

Изменение flex-direction

Добавление свойства flex-direction в контейнер позволяет нам изменять направление, в котором отображаются наши элементы flex. Установка flex-direction: row-reverse сохранит порядок отображения элементов вдоль строки, однако начало и конец строки поменяются местами.

Если изменить значение свойства flex-direction на column, главная ось изменится, и наши элементы будут отображаются в столбец. При установке параметра column-reverse, начало и конец столбца поменяются местами.

В приведённом ниже примере значение свойства flex-direction установлено как row-reverse. Попробуйте другие значения — row, column и column-reverse, чтобы посмотреть как изменятся элементы контейнера.

Многострочный флекс-контейнер с flex-wrap

Несмотря на то, что флекс-бокс — это однонаправленная модель, есть возможность завернуть наши флекс-элементы в несколько строк. При этом вы должны рассматривать каждую строку как новый флекс контейнер. Распределение пространства будет происходить на этой конкретной линии, не привязываясь к соседним линиям.

Чтобы включить такое поведение, добавьте параметр flex-wrap со значением wrap. Теперь, как только ваши элементы будут слишком большими для того, чтобы влезать на одну строчку, они будут переноситься на новые строки. Живой пример ниже содержит широкие элементы, у которых общая ширина больше, чем размер контейнера. Так как параметр flex-wrap установлен в значение wrap, элементы переносятся. Если вы установите значение nowrap, то есть в начальное значение, то элементы ужмутся так, чтобы все элементы поместились на одной строке, потому что у них установлено значение, позволяющее им ужиматься при необходимости. Если им запретить ужиматься, или если они не смогут ужаться достаточно сильно, то при установленном значении nowrap будет происходить переполнение контейнера.

Более подробно эту тема разбирается в статье Разбираемся с обёртыванием Flex элементов.

Краткая запись направления и многострочности: flex-flow

Вы можете указать два свойства flex-direction и flex-wrap в одном flex-flow. Первое значение свойства определяет flex-direction, второе flex-wrap.

В приведённом ниже примере вы можете изменить первое значение на одно из доступных для flex-directionrow, row-reverse, column or column-reverse, а второе на wrap или nowrap, чтобы посмотреть как изменятся элементы контейнера.

Свойства, применяемые к флекс-элементам

Управлять поведением флекс-элементов более детально мы можем с помощью их собственных свойств:

  • flex-grow
  • flex-shrink
  • flex-basis

В этом обзоре мы лишь кратко рассмотрим эти свойства. Чтобы получить более глубокое понимание обратитесь к руководству Управление соотношением элементов вдоль главной оси.

Чтобы понять как работают эти свойства, прежде нам необходимо разобраться с концепцией доступного пространства. Изменяя значения этих флекс свойств, мы влияем на то, как доступное пространство распределяется между нашими элементами. Эта концепция так же важна для выравнивания элементов.

Если наш контейнер шириной 500 пикселей содержит три элемента шириной 100 пикселей каждый, для их размещения нам потребуется пространство шириной в 300 пикселей. Остаётся 200 пикселей свободного пространства. Если мы не изменим исходные значения этих свойств, флексбокс разместит это пространство за последним элементом.

This flex container has available space after laying out the items.

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

Свойство flex-basis

Свойство flex-basis определяет размер доступного пространства элемента. Начальное значение этого свойства — auto — в этом случае браузер проверяет, имеют ли элементы размер. В приведённом выше примере все элементы имеют ширину 100px, и этот размер читается браузером как flex-basis.
Если элементы не имеют размера, то для размера flex-basis используется размер контента. Вот почему, когда мы просто объявляем display: flex на родительском элементе для создания flex-элементов, все элементы перемещаются в ряд и занимают столько места, сколько им нужно для отображения их содержимого.

Свойство flex-grow

With the flex-grow property set to a positive integer, flex items can grow along the main axis from their flex-basis. This will cause the item to stretch and take up any available space on that axis, or a proportion of the available space if other items are allowed to grow too.

If we gave all of our items in the example above a flex-grow value of 1 then the available space in the flex container would be equally shared between our items and they would stretch to fill the container on the main axis.

The flex-grow property can be used to distribute space in proportion. If we give our first item a flex-grow value of 2 and the other items a value of 1, 2 parts will be given to the first item (100px out of 200px in the case of the example above), 1 part each the other two (50px each out of the 200px total).

Свойство flex-shrink

Where the flex-grow property deals with adding space in the main axis, the flex-shrink property controls how it is taken away. If we do not have enough space in the container to lay out our items and flex-shrink is set to a positive integer the item can become smaller than the flex-basis. As with flex-grow different values can be assigned in order to cause one item to shrink faster than others — an item with a higher value set for flex-shrink will shrink faster than its siblings that have lower values.

The minimum size of the item will be taken into account while working out the actual amount of shrinkage that will happen, which means that flex-shrink has the potential to appear less consistent than flex-grow in behavior. We’ll therefore take a more detailed look at how this algorithm works in the article Controlling Ratios of items along the main axis.

Примечание: Note that these values for flex-grow and flex-shrink are proportions. Typically if we had all of our items set to flex: 1 1 200px and then wanted one item to grow at twice the rate, we would set that item to flex: 2 1 200px. However you could use flex: 10 1 200px and flex: 20 1 200px if you wanted.

Краткая запись значений флекс свойств

You will very rarely see the flex-grow, flex-shrink, and flex-basis properties used individually; instead they are combined into the flex shorthand. The flex shorthand allows you to set the three values in this order — flex-grow, flex-shrink, flex-basis.

The live example below allows you to test out the different values of the flex shorthand; remember that the first value is flex-grow. Giving this a positive value means the item can grow. The second is flex-shrink — with a positive value the items can shrink, but only if their total values overflow the main axis. The final value is flex-basis; this is the value the items are using as their base value to grow and shrink from.

There are also some predefined shorthand values which cover most of the use cases. You will often see these used in tutorials, and in many cases these are all you will need to use. The predefined values are as follows:

  • flex: initial
  • flex: auto
  • flex: none
  • flex: <positive-number>

Setting flex: initial resets the item to the initial values of Flexbox. This is the same as flex: 0 1 auto. In this case the value of flex-grow is 0, so items will not grow larger than their flex-basis size. The value of flex-shrink is 1, so items can shrink if they need to rather than overflowing. The value of flex-basis is auto. Items will either use any size set on the item in the main dimension, or they will get their size from the content size.

Using flex: auto is the same as using flex: 1 1 auto; everything is as with flex:initial but in this case the items can grow and fill the container as well as shrink if required.

Using flex: none will create fully inflexible flex items. It is as if you wrote flex: 0 0 auto. The items cannot grow or shrink but will be laid out using flexbox with a flex-basis of auto.

The shorthand you often see in tutorials is flex: 1 or flex: 2 and so on. This is as if you used flex: 1 1 0. The items can grow and shrink from a flex-basis of 0.

Try these shorthand values in the live example below.

Alignment, justification and distribution of free space between items

A key feature of flexbox is the ability to align and justify items on the main- and cross-axes, and to distribute space between flex items.

align-items

The align-items property will align the items on the cross axis.

The initial value for this property is stretch and this is why flex items stretch to the height of the tallest one by default. They are in fact stretching to fill the flex container — the tallest item is defining the height of that.

You could instead set align-items to flex-start in order to make the items line up at the start of the flex container, flex-end to align them to the end, or center to align them in the centre. Try this in the live example — I have given the flex container a height in order that you can see how the items can be moved around inside the container. See what happens if you set the value of align-items to:

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

justify-content

The justify-content property is used to align the items on the main axis, the direction in which flex-direction has set the flow. The initial value is flex-start which will line the items up at the start edge of the container, but you could also set the value to flex-end to line them up at the end, or center to line them up in the centre.

You can also use the value space-between to take all the spare space after the items have been laid out, and share it out evenly between the items so there will be an equal amount of space between each item. To cause an equal amount of space on the right and left of each item use the value space-around. With space-around, items have a half-size space on either end. Or, to cause items to have equal space around them use the value space-evenly. With space-evenly, items have a full-size space on either end.

Try the following values of justify-content in the live example:

  • flex-start
  • flex-end
  • center
  • space-around
  • space-between
  • space-evenly

In the article Aligning Items in a Flex Container we will explore these properties in more depth, in order to have a better understanding of how they work. These simple examples however will be useful in the majority of use cases.

Next steps

After reading this article you should have an understanding of the basic features of Flexbox. In the next article we will look at how this specification relates to other parts of CSS (en-US).

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

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

CSS Flexible Box Layout Module (CSS модуль для макетов с гибкими блоками), коротко flexbox (Флексбокс), создана, чтобы убрать недостатки при создании самых разных HTML конструкций, в том числе адаптированных под разную ширину и высоту, и сделать верстку логичной и простой. А логичный подход, как правило работает в неожиданных местах, там где результат не проверялся — логика наше все!

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

Базовые знания

FlexBox состоит из Контейнера и его Дочерних элементов (items) (гибких элементов).

  • Главная ось — главное направление движения элементов внутри контейнера. Направление главной оси можно изменить с помощью свойства flex-direction. Обратите внимание, что при смене осей, меняются только направления движения блоков внутри, а начало, конец и размер контейнера остаются прежними.

  • Начало и конец главной оси — элементы располагаются от начала и до конца контейнера.

  • Поперечная ось — направление движения элементов, когда они не умещаются в контейнер по направлению главной оси. Поперечная ось всегда перпендикулярна (⊥) главной.

  • Начало и конец поперечной оси — по поперечной оси заполняются ряды от начала и до конца контейнера. В каждом таком ряду располагаются элементы (читайте ниже).

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

Для включения flexbox, любому HTML элементу достаточно присвоить css свойство display:flex; или display:inline-flex;.

<style>
	.flex{ display: flex; }
</style>
<div class="flex">
	<div class="item">1</div>
	<div class="item">2</div>
</div>

После включения flex свойства, внутри контейнера создаются две оси: главная и поперечная (перпендикулярная (⊥), кросс ось). Все вложенные элементы (первого уровня) выстраиваются по главной оси. По умолчанию главная ось горизонтальная и имеет направление слева направо (→), а кросс ось соответственно вертикальная и направлена сверху вниз (↓).

Главную и кросс оси можно поменять местами, тогда элементы будут располагаться сверху вниз (↓) и когда перестанут вмещаться в высоту то будут двигаться слева направо (→) — то есть оси просто поменялись местами. При этом начало и конец расположения элементов не меняется — меняются только направления (оси)! Именно поэтому нужно представлять себе оси внутри контейнера. Однако не нужно думать, что есть какие-то там «физические» оси и они на что-то влияют. Ось тут — это только лишь направление движения элементов внутри контейнера. Например, если мы указали выравнивание элементов по центру основной оси и потом изменили направление этой основной оси, то изменится и выравнивание: элементы были в середине по горизонтали, а стали в середине по вертикали… См. пример.

Еще одной важной особенностью Флекс-бокс является наличие рядов в поперечном направлении. Чтобы понять о чем речь, давайте представим что есть главная горизонтальная ось, много элементов и они не «лезут» в контейнер, поэтому переходят на другой ряд. Т.е. контейнер выглядит так: контейнер, внутри него два ряда, в каждом ряду по несколько элементов. Представили? А теперь запомните, что выравнивать по вертикали мы можем не только элементы, но и ряды! Как это работает хорошо видно в примере к свойству align-content. А вот так это выглядит схематически:

CSS свойства, которые могут влиять на модель построения макета: float, clear, vertical-align, columns не работают во flex конструкции. Тут используется другая модель построения макета и эти css свойства просто игнорируются.

CSS свойства Flexbox

Flexbox содержит разные css правила для управления всей flex конструкцией. Одни нужно применять к основному контейнеру, а другие к элементам этого контейнера.

Для контейнера

display:

Включает flex свойство для элемента. Под это свойство попадает сам элемент и вложенные в него элементы: затрагиваются только потомки первого уровня — они станут элементами flex контейнера.

  • flex — элемент растягивается на всю ширину и имеет свое полное пространство среди окружающих блоков. Происходит перенос строк в начале и в конце блока.
  • inline-flex — элемент обтекается другими элементами. При этом его внутренняя часть форматируется как блочный элемент, а сам элемент — как встроенный.

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

flex-direction:

Изменяет направление главной оси контейнера. Поперечная ось меняется соответственно.

  • row (default) — направление элементов слева направо (→)
  • column — направление элементов сверху вниз (↓)
  • row-reverse — направление элементов справа налево (←)
  • column-reverse — направление элементов снизу вверх (↑)

Нужно понимать, что при переходе с row на column или с row-reverse на column-reverse меняется только направление осей и больше ничего. Начало и конец расположения блоков остается неизменным (см. картинку в начале). Т.е. если при row элементы начинали свой путь справа/сверху, то при column все останется также — изменится только направление… (см. пример свойства flex-wrap)

flex-wrap:

Управляет переносом непомещающихся в контейнер элементов.

  • nowrap (default) — вложенные элементы располагаются в один ряд (при direction=row) или в одну колонку (при direction=column) независимо от того помещаются они в контейнер или нет.
  • wrap — включает перенос элементов на следующий ряд, если они не помещаются в контейнер. Так включается движение элементов по поперечной оси.
  • wrap-reverse — тоже что wrap только перенос будет не вниз, а вверх (в обратном направлении).
flex-flow: direction wrap

Объединяет оба свойства flex-direction и flex-wrap. Они часто используются вместе, поэтому чтобы писать меньше кода было создано свойство flex-flow.

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

/* только flex-direction */
flex-flow: row;
flex-flow: row-reverse;
flex-flow: column;
flex-flow: column-reverse;

/* только flex-wrap */
flex-flow: nowrap;
flex-flow: wrap;
flex-flow: wrap-reverse;

/* сразу оба значения: flex-direction и flex-wrap */
flex-flow: row nowrap;
flex-flow: column wrap;
flex-flow: column-reverse wrap-reverse;
justify-content:

Выравнивает элементы по основной оси: если direction=row, то по горизонтали, а если direction=column, то по вертикали.

  • flex-start (default) — элементы будут идти с начала (в конце может остаться место).
  • flex-end — элементы выравниваются по концу (место останется в начале)
  • center — по центру (место останется слева и права)
  • space-between — крайние элементы прижимаются к краям (место между элементами распределяется равномерно)
  • space-around — свободное пространство равномерно распределяется между элементами (крайние элементы не прижимаются к краям). Пространство между краем контейнера и крайними элементами будет в два раза меньше чем пространство между элементами в середине ряда.
  • space-evenly — тоже что space-around, только расстояние у крайних элементов до краев контейнера такое же как и между элементами.
align-content:

Выравнивает ряды, в которых находятся элементы по поперечной оси. То же что justify-content только для противоположной оси.

Заметка: Работает только когда высота контейнера фиксированная (выше чем ряды внутри него).

Т.е. если flex-direction: row, то это свойство будет выравнивать невидимые ряды по вертикали ¦. Тут важно заметить, что высота блока должна быть задана жестко и должна быть больше высоты рядов иначе сами ряды будут растягивать контейнер и любое их выравнивание теряет смысл, потому что между ними нет свободного места… А вот когда flex-direction: column, то ряды движется по горизонтали и ширина контейнера почти всегда больше ширины рядов и выравнивание рядов сразу приобретает смысл…

Это свойство мало где нужно и вместо него чаще используется align-items (см.ниже).

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

Выравнивает элементы по поперечной оси внутри ряда (невидимой строки). Т.е. сами ряды выравниваются через align-content, а элементы внутри этих рядов (строк) через align-items и все это по поперечной оси. По главной оси такого разделения нет, там нет понятия рядов и элементы выравниваются через justify-content.

  • stretch (default) — элементы растягиваются заполняя строку полностью
  • flex-start — элементы прижимаются к началу ряда
  • flex-end — элементы прижимаются к концу ряда
  • center — элементы выравниваются по центру ряда
  • baseline — элементы выравниваются по базовой линии текста
column-gap:
gap:

Задает размер промежутка между элементами контейнера. Соответственно:

  • column-gap: — раздвигает только колонки.
  • gap: — раздвигает и колонки и ряды.

Размеры можно указать в абсолютных или относительных величинах: px, em, ... или в %.

Поддержка gap {percent} ( у column-gap поддержка точно такая же ):

Для элементов контейнера

flex-grow:

Задает коэффициент увеличения элемента при наличии свободного места в контейнере. По умолчанию flex-grow: 0 т.е. никакой из элементов не должен увеличиваться и заполнять свободное место в контейнере.

По умолчанию flex-grow: 0

Примеры:

  • Если всем элементам указать flex-grow:1, то все они растянуться одинаково и заполнять все свободное место в контейнере.
  • Если одному из элементов указать flex-grow:1, то он заполнит все свободное место в контейнере и выравнивания через justify-content работать уже не будут: свободного места нет выравнивать нечего…
  • При flex-grow:1. Если один из них имеет flex-grow:2, то он будет в 2 раза больше, чем все остальные
  • Если все flex-блоки внутри flex-контейнера имеют flex-grow:3, то они будут одинакового размера
  • При flex-grow:3. Если один из них имеет flex-grow:12, то он будет в 4 раза больше, чем все остальные

Как это работает? Допустим, что контейнер имеет ширину 500px и содержит два элемента, каждый из которых имеет базовую ширину 100px. Значит в контейнере остается 300 свободных пикселей. Теперь, если первому элементу укажем flex-grow:2;, а второму flex-grow: 1;, то блоки займут всю доступную ширину контейнера и ширина первого блока будет 300px, а второго 200px. Объясняется это тем, что доступные 300px свободного места в контейнере распределились между элементами в соотношении 2:1, +200px первому и +100px второму.

Заметка: в значении можно указывать дробные числа, например: 0.5 — flex-grow:0.5

flex-shrink:

Задает коэффициент уменьшения элемента. Свойство противоположное flex-grow и определяет как элемент должен сжиматься, если в контейнере не остается свободного места. Т.е. свойство начинает работать, когда сумма размеров всех элементов больше чем размер контейнера.

По умолчанию flex-shrink:1

Допустим, что контейнер имеет ширину 600px и содержит два элемента, каждый из которых имеет ширину 300px — flex-basis:300px;. Т.е. два элемента полностью заполняют контейнер. Первому элементу укажем flex-shrink: 2;, а второму flex-shrink: 1;. Теперь уменьшим ширину контейнера на 300px, т.е. элементы должны сжаться на 300px чтобы находится внутри контейнера. Сжиматься они будут в соотношении 2:1, т.е. первый блок сожмется на 200px, а второй на 100px и новые размеры элементов станут 100px и 200px.

Заметка: в значении можно указывать дробные числа, например: 0.5 — flex-shrink:0.5

flex-basis:

Устанавливает базовую ширину элемента — ширину до того как будут высчитаны остальные условия влияющие на ширину элемента. Значение можно указать в px, em, rem, %, vw, vh и т.д. Итоговая ширина будет зависеть от базовой ширины и значений flex-grow, flex-shrink и контента внутри блока. При auto элемент получает базовую ширину относительно контента внутри него.

По умолчанию: auto

Иногда лучше установить ширину элемента жестко через привычное свойство width. Например, width: 50%; будет означать, что элемент внутри контейнера будет ровно 50%, однако при этом все также будут работать свойства flex-grow и flex-shrink. Такое может быть нужно, когда элемент растягивается контентом внутри него, больше указанного во flex-basis. Пример смотрите в заметках.

flex-basis будет «жестким», если обнулить растяжение и сжатие: flex-basis:200px; flex-grow:0; flex-shrink:0;. Все это можно записать так flex:0 0 200px;.

flex: {grow shrink basis}

Короткая запись трех свойств: flex-grow flex-shrink flex-basis.

По умолчанию: flex: 0 1 auto

Однако можно указать и одно, и два значения:

flex: none; /* 0 0 auto */

/* число */
flex: 2; /* flex-grow (flex-basis переходит в 0) */

/* не число */
flex: 10em;    /* flex-basis: 10em */
flex: 30px;    /* flex-basis: 30px */
flex: auto;    /* flex-basis: auto */
flex: content; /* flex-basis: content */

flex: 1 30px; /* flex-grow и flex-basis */

flex: 2 2; /* flex-grow и flex-shrink (flex-basis переходит в 0) */

flex: 2 2 10%; /* flex-grow и flex-shrink и flex-basis */
align-self:

Позволяет изменить свойство align-items, только для отдельного элемента.

По умолчанию: от align-items контейнера

  • stretch — элемент растягиваются заполняя строку полностью
  • flex-start — элемент прижимаются к началу строки
  • flex-end — элемент прижимаются к концу строки
  • center — элемент выравниваются по центру строки
  • baseline — элемент выравниваются по базовой линии текста

order:

Позволяет менять порядок (позицию, положение) элемента в общем ряду.

По умолчанию: order: 0

По умолчанию элементы имеют order: 0 и ставятся в порядке их появления в HTML коде и направления ряда. Но если изменить значение свойства order, то элементы будут выстраиваться в порядке значений: -1 0 1 2 3 …. Например если одному из элементов указать order: 1, то сначала будут идти все нулевые, а потом элемент с 1.

Так можно, например, первый элемент перекинуть в конец, при этом не меняя направление движения остальных элементов или HTML код.

Заметки

Чем отличается flex-basis от width?

Ниже важные различия между flex-basis и width / height:

  • flex-basis работает только для главной оси. Это значит что при flex-direction:row flex-basis контролирует ширину (width), а при flex-direction:column контролирует высоту (height). Смотрите пример.

  • flex-basis применяется только к flex элементам. А значит если отключить flex у контейнера это свойство не будет иметь эффекта.

  • Абсолютные элементы контейнера не участвуют во flex конструкции… А значит, flex-basis не влияет на элементы flex контейнера, если они абсолютны position:absolute. Им нужно будет указать width / height.

  • При использовании css свойства flex три значения: flex-grow / flex-shrink / flex-basis можно скомбинировать и записать коротко — flex:0 0 50%. Тогда как при использовании width, grow и shrink придется писать отдельно. Например: flex:0 0 50% == width:50%; flex-shrink:0;. Иногда это просто неудобно.

По возможности все же отдавайте предпочтение flex-basis. Используйте width только когда не подходит flex-basis.

Отличие flex-basis от width — баг или фича?

Контент внутри flex элемента распирает его и не может выйти за его пределы. Однако если установить ширину через width или max-width, а не flex-basis, то элемент внутри flex контейнера сумеет выйти за пределы этого контейнера (иногда нужно именно такое поведение). Пример:

Примеры Flex верстки

В примерах нигде не используются префиксы для кроссбраузерности. Сделал я так для удобного чтения css. Поэтому примеры смотрите в последних версиях Chrome или Firefox.

#1 Простой пример с выравниванием по вертикали и горизонтали

Начнем с самого простого примера — выравнивание по вертикали и горизонтали одновременно и при любой высоте блока, даже резиновой.

<div class="parent">
	<span class="child">Текст по середине</span>
</div>

<style>
	.parent { display: flex; }
	.child { margin: auto; }
</style>

Или так, без блока внутри:

<div class="center-text">
	Текст по середине
</div>

<style>
.center-text {
	display: flex;
	justify-content: center;
	align-items: center;
}
</style>

#1.2 Разделение (разрыв) между элементами флекс блока

Чтобы расположить элементы контейнера по краям и произвольно выбрать элемент после которого будет разрыв, нужно использовать свойство margin-left:auto или margin-right:auto.

#2 Адаптивное меню на flex

Сделаем меню в самом верху страницы. На широком экране оно должно быть справа. На среднем выравниваться по середине. А на маленьком каждый элемент должен быть на новой строке.

<div class="nav">
	<a href="#">Главная</a>
	<a href="#">О нас</a>
	<a href="#">Продукты</a>
	<a href="#">Контакты</a>
</div>

<style>
.nav {
	display: flex;
	justify-content: flex-end; /* разместим справа */

	background: #6e9cc3;
}

.nav a {
	color:#fff; padding:15px 10px; text-decoration:none; text-align:center;
}
.nav a:hover { background:#5c8db7; }

/* меньше 800px */
@media all and (max-width: 800px) {
	.nav { justify-content: space-around; }
	.nav a{ flex-grow:1; /* растягиваться на всю ширину */ }
}

/* меньше 500px */
@media all and (max-width: 500px) {
	.nav { flex-direction: column; }
}
</style>

Перейдите в jsfiddle.net и изменяйте ширину секции «результат»

#3 Адаптивные 3 колонки

Этот пример показывает как быстро и удобно сделать 3 колонки, которые при сужении будут превращаться в 2 и затем в 1.

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

<div class="flex">
	<div class="item">1</div>
	<div class="item">2</div>
	<div class="item">3</div>
	<div class="item">4</div>
	<div class="item">5</div>
	<div class="item">6</div>
</div>

<style>
.flex{
	display: flex;
	flex-wrap: wrap;

	max-width: 700px; /* макс ширина */
	margin: 0 auto; /* выровняем по центру */
}

.item{
	flex:1 1 calc(33.33% - 30px); /* отнимем margin и скажем растягиваться */
	margin:5px;
	box-sizing:border-box; /* чтобы внутренний отступ не влиял когда там будет текст... */
	min-width:170px; /* мин. ширина блока, чтобы переносились на другой ряд */

	padding:50px 20px; font-size:400%; text-align:center; background:#b5ced8; /* для красоты */
}
</style>

Перейдите в jsfiddle.net и изменяйте ширину секции «результат»

#4 Адаптивные блоки на flex

Допустим нам нужно вывести 3 блока, один большой и два маленьких. При этом нужно чтобы блоки подстраивались под маленькие экраны. Делаем:

<div class="flex">
	<div class="mainitem">1</div>
	<div class="sideitem">
		<div class="item">2</div>
		<div class="item">3</div>
	</div>
</div>

<style>
.flex{
	display: flex;

	max-width: 700px; /* макс ширина блока */
	margin: 0 auto; /* выравниваем блок по центру */
	font-size:400%;
}

.mainitem, .item{
	flex-grow:1; /* растягивание элементов */

	background:#b5ced8;
	display: flex; justify-content: center; align-items: center; /* цифры по центру */
}

.mainitem{
	min-height:300px; /* высота основного блока */
}

.sideitem{
	/* flex:0 0 150px; */
	flex-basis:150px; /* ширина 150 */
	flex-shrink:0; /* Убираем уменьшение = 150 */

	display: flex;
	flex-direction: column;
}

.item{
	flex-basis:50%;
	min-height:150px;
	margin-left:10px;
}
.item:first-child{ margin-bottom:10px; }

/* меньше 600px */
@media screen and (max-width: 600px) {
	.flex{ flex-wrap: wrap; } /* для переноса */

	.sideitem{ flex-direction:row; flex-basis:100%; }

	.item{ margin-left:0; margin-top:10px; }
	.item:first-child{ margin-bottom:0; margin-right:10px; }
}

/* меньше 450px */
@media screen and (max-width: 450px) {
	.sideitem{ flex-wrap: wrap; } /* разрешаем перенос */
	.item{ flex-basis:100%; } /* на всю ширину */
	.item:first-child{ margin-right:0; }
}
</style>

Перейдите в jsfiddle.net и изменяйте ширину секции «результат»

#5 Галерея на flex и transition

Этот пример показывает как быстро можно сделать симпатичный аккордеон с картинками на flex. Обратите внимание на свойство transition для flex.

<div class="flex">
  <div class="item img1"></div>
  <div class="item img2"></div>
  <div class="item img3"></div>
  <div class="item img4"></div>
  <div class="item img5"></div>
</div>

<style>
.flex {
	display: flex;

	overflow:hidden; /*скроем тень*/
}
.item {
	height:300px;

	flex:20%; /* = flex-basis:20%; */

	transition: flex 300ms ease;

	box-shadow: 0 0 19px 3px #000; margin: 1px; /* красивости тени */
}
.item:hover {
	 flex: 0.1 0.1 400px;
	background-size: 100% 100%
}

.img1 { background: url('http://lorempixel.com/400/300/cats/1') 0 0 no-repeat; }
.img2 { background: url('http://lorempixel.com/400/300/cats/2') 0 0 no-repeat; }
.img3 { background: url('http://lorempixel.com/400/300/cats/3') 0 0 no-repeat; }
.img4 { background: url('http://lorempixel.com/400/300/cats/4') 0 0 no-repeat; }
.img5 { background: url('http://lorempixel.com/400/300/cats/5') 0 0 no-repeat; }
</style>

#6 Флекс во флекс (просто пример)

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

Для решения этой задачи, сами блоки растягиваются флексом и им установлена максимально возможная ширина. Каждый внутренний блок также является флекс конструкцией, с повернутой осью flex-direction:column; и элемент в середине (где находится текст) растягивается flex-grow:1; чтобы заполнить всё свободное пространство, так достигается результат — текст начинался с одной линии…

Еще примеры

Смотрите здесь alexriz.github.io

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

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

Чтобы знать какие префиксы актуальны на сегодня (июнь. 2019), приведу пример всех flex правил с нужными префиксами:

/* Контейнер */
.flex {

	display:-ms-flexbox;
	display:flex;

	display:-ms-inline-flexbox;
	display:inline-flex;

	-ms-flex-direction:column;
	flex-direction:column;

	-ms-flex-wrap:wrap;
	flex-wrap:wrap;

	-ms-flex-flow:column wrap;
	flex-flow:column wrap;

	-ms-flex-pack:justify;
	justify-content:space-between;

	-ms-flex-line-pack:distribute;
	align-content:space-around;
}

/* Элементы */
.flex-item {

	-ms-flex-positive:1;
	flex-grow:1;

	-ms-flex-negative:2;
	flex-shrink:2;

	-ms-flex-preferred-size:100px;
	flex-basis:100px;

	-ms-flex:1 2 100px;
	flex:1 2 100px;

	-ms-flex-item-align:center;
	align-self:center;

	-ms-flex-order:2;
	order:2;

}

Лучше если свойства с префиксами будут идти до оригинального свойства.
В этом списке нет ненужных на сегодня (по caniuse) префиксов, но вообще префиксов больше.

Видео

Ну и не забывайте про видео, там порой тоже интересно и понятно. Вот парочка популярных:

Полезные ссылки по Flex

  • flexboxfroggy.com — игра обучающая flexbox.

  • Flexplorer — наглядный конструктор flex кода.

  • Шпаргалка Flexbox

Использовал при написании:

  • https://habrahabr.ru/post/242545/
  • http://html5.by/blog/flexbox/
  • https://css-tricks.com/snippets/css/a-guide-to-flexbox/
  • https://www.w3.org/TR/css-flexbox-1/

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

  • row
  • row-reverse
  • column
  • column-reverse

Значения относительно простые — они позволяют указать, располагаются ли флекс-элементы в рядах или колонках, в обратном порядке или нет. Но конечное направление зависит от writing-mode.

Значение row

Это исходное значение, так что если вы не установите свойство flex-direction, именно это значение будет применяться.

<!doctype html>
<title>Пример</title>
<style>
.container {
display: flex;
flex-direction: row;
align-items: flex-start;
background: beige;
height: 100vh;
}
.red {
background: orangered;
}
.green {
background: yellowgreen;
}
.blue {
background: steelblue;
}
.container > div {
font-size: 5vw;
padding: .5em;
color: white;
}
body {
margin: 0;
}
</style>
<div class=»container»>
<div class=»red»>1</div>
<div class=»green»>2</div>
<div class=»blue»>3</div>
</div>

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

Вот что произойдёт, если мы применим writing-mode: vertical-rl к приведённому выше примеру.

<!doctype html>
<title>Пример</title>
<style>
.container {
display: flex;
flex-direction: row;
align-items: flex-start;
background: beige;
height: 100vh;
writing-mode: vertical-rl;
}
.red {
background: orangered;
}
.green {
background: yellowgreen;
}
.blue {
background: steelblue;
}
.container > div {
font-size: 5vw;
padding: .5em;
color: white;
}
body {
margin: 0;
}
</style>
<div class=»container»>
<div class=»red»>1</div>
<div class=»green»>2</div>
<div class=»blue»>3</div>
</div>

А вот что произойдёт, если мы добавим direction: rtl в этот пример.

<!doctype html>
<title>Пример</title>
<style>
.container {
display: flex;
flex-direction: row;
align-items: flex-start;
background: beige;
height: 100vh;
writing-mode: vertical-rl;
direction: rtl;
}
.red {
background: orangered;
}
.green {
background: yellowgreen;
}
.blue {
background: steelblue;
}
.container > div {
font-size: 5vw;
padding: .5em;
color: white;
}
body {
margin: 0;
}
</style>
<div class=»container»>
<div class=»red»>1</div>
<div class=»green»>2</div>
<div class=»blue»>3</div>
</div>

Сделаем ещё один шаг вперёд и добавим text-orientation: upright в этот пример. Вот что получилось.

<!doctype html>
<title>Пример</title>
<style>
.container {
display: flex;
flex-direction: row;
align-items: flex-start;
background: beige;
height: 100vh;
writing-mode: vertical-rl;
direction: rtl;
text-orientation: upright;
}
.red {
background: orangered;
}
.green {
background: yellowgreen;
}
.blue {
background: steelblue;
}
.container > div {
font-size: 5vw;
padding: .5em;
color: white;
}
body {
margin: 0;
}
</style>
<div class=»container»>
<div class=»red»>1</div>
<div class=»green»>2</div>
<div class=»blue»>3</div>
</div>

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

Этот же принцип применим ко всем другим значениям flex-direction, показанных ниже.

Значение row-reverse

Вы можете использовать flex-direction: row-reverse, чтобы элементы в ряду отображались в обратном порядке.

<!doctype html>
<title>Пример</title>
<style>
.container {
display: flex;
flex-direction: row-reverse;
align-items: flex-start;
background: beige;
height: 100vh;
}
.red {
background: orangered;
}
.green {
background: yellowgreen;
}
.blue {
background: steelblue;
}
.container > div {
font-size: 5vw;
padding: .5em;
color: white;
}
body {
margin: 0;
}
</style>
<div class=»container»>
<div class=»red»>1</div>
<div class=»green»>2</div>
<div class=»blue»>3</div>
</div>

Значение column

Использование flex-direction: column изменяет распределение флекс-элементов так, чтобы они располагались в колонку.

<!doctype html>
<title>Пример</title>
<style>
.container {
display: flex;
flex-direction: column;
align-items: flex-start;
background: beige;
height: 100vh;
}
.red {
background: orangered;
}
.green {
background: yellowgreen;
}
.blue {
background: steelblue;
}
.container > div {
font-size: 5vw;
padding: .5em;
color: white;
}
body {
margin: 0;
}
</style>
<div class=»container»>
<div class=»red»>1</div>
<div class=»green»>2</div>
<div class=»blue»>3</div>
</div>

Значение column-reverse

Значение flex-direction: column-reverse устанавливает элементы в колонке в обратном порядке.

<!doctype html>
<title>Пример</title>
<style>
.container {
display: flex;
flex-direction: column-reverse;
align-items: flex-start;
background: beige;
height: 100vh;
}
.red {
background: orangered;
}
.green {
background: yellowgreen;
}
.blue {
background: steelblue;
}
.container > div {
font-size: 5vw;
padding: .5em;
color: white;
}
body {
margin: 0;
}
</style>
<div class=»container»>
<div class=»red»>1</div>
<div class=»green»>2</div>
<div class=»blue»>3</div>
</div>

Переносы флекс-элементов

Вы можете использовать свойство flex-wrap и определить, как флекс-элементы переносятся внутри флекс-контейнера.

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

Значение nowrap

Вот что я имею в виду (это поведение по умолчанию).

<!doctype html>
<title>Пример</title>
<style>
.container {
display: flex;
flex-direction: row;
align-items: flex-start;
background: beige;
height: 100vh;
}
.red {
background: orangered;
}
.green {
background: yellowgreen;
}
.blue {
background: steelblue;
}
.container > div {
font-size: 5vw;
padding: .5em;
color: white;
width: 60%;
}
body {
margin: 0;
}
</style>
<div class=»container»>
<div class=»red»>1</div>
<div class=»green»>2</div>
<div class=»blue»>3</div>
</div>

У всех флекс-элементов в данном примере ширина задана как 60%. Это 60 процентов от ширины флекс-контейнера. Вы не можете разместить два элемента такой ширины рядом друг с другом, не говоря уже о трёх. Но поскольку начальное значение flex-wrap равно nowrap, то элементы не переносятся, а вместо этого они сжимаются.

Значение wrap

Теперь давайте добавим flex-wrap: wrap.

<!doctype html>
<title>Пример</title>
<style>
.container {
display: flex;
flex-direction: row;
align-items: flex-start;
background: beige;
height: 100vh;
flex-wrap: wrap;
}
.red {
background: orangered;
}
.green {
background: yellowgreen;
}
.blue {
background: steelblue;
}
.container > div {
font-size: 5vw;
padding: .5em;
color: white;
width: 60%;
}
body {
margin: 0;
}
</style>
<div class=»container»>
<div class=»red»>1</div>
<div class=»green»>2</div>
<div class=»blue»>3</div>
</div>

Значение wrap-reverse

Давайте теперь добавим flex-wrap: wrap-reverse.

<!doctype html>
<title>Пример</title>
<style>
.container {
display: flex;
flex-direction: row;
align-items: flex-start;
background: beige;
height: 100vh;
flex-wrap: wrap-reverse;
}
.red {
background: orangered;
}
.green {
background: yellowgreen;
}
.blue {
background: steelblue;
}
.container > div {
font-size: 5vw;
padding: .5em;
color: white;
width: 60%;
}
body {
margin: 0;
}
</style>
<div class=»container»>
<div class=»red»>1</div>
<div class=»green»>2</div>
<div class=»blue»>3</div>
</div>

Свойство flex-flow

Свойство flex-flow является сокращением для свойств flex-direction и flex-wrap, поэтому вы можете указать их одновременно. Вот пример.

<!doctype html>
<title>Пример</title>
<style>
.container {
display: flex;
flex-direction: row;
align-items: flex-start;
background: beige;
height: 100vh;
flex-flow: row-reverse wrap;
}
.red {
background: orangered;
}
.green {
background: yellowgreen;
}
.blue {
background: steelblue;
}
.container > div {
font-size: 5vw;
padding: .5em;
color: white;
width: 60%;
}
body {
margin: 0;
}
</style>
<div class=»container»>
<div class=»red»>1</div>
<div class=»green»>2</div>
<div class=»blue»>3</div>
</div>

См. также

Последнее изменение: 11.03.2020

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

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

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

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

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

Основы

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

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

Flexbox

В основном элементы будут распределяться либо вдоль главной оси
(от 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: элементы распределяются равномерно с равным расстоянием
    между собой и границами строки.

justify-content

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-items

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 (по умолчанию): строки растягиваются, заполняя свободное
    пространство.

align-content

order

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

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

flex-grow

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

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

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

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

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

flex-shrink

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

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

flex-shrink: <number> (default 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;
}

Готово. Всё остальное — уже дело оформления. Ниже размещён CodePen,
демонстрирующий этот пример. Обязательно попробуйте растянуть/сжать окно
браузера и посмотрите, что произойдёт.

Check out this Pen!

<script async src=»http://codepen.io/assets/embed/ei.js»></script>

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

/* Большие экраны */
.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;
  }
}
Check out this Pen!

<script async src=»http://codepen.io/assets/embed/ei.js»></script>

Давайте попробуем кое-что получше и поиграем с гибкостью 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; }
}
Check out this Pen!

<script async src=»http://codepen.io/assets/embed/ei.js»></script>

Похожие свойства

  • Grid

Другие ресурсы

  • Flexbox in the CSS specifications
  • Flexbox at MDN
  • Flexbox at Opera
  • Diving into Flexbox by Bocoup
  • Mixing syntaxes for best browser support on CSS-Tricks
  • Flexbox by Raphael Goetter (FR)
  • Flexplorer by Bennett Feely

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

  • (modern) означает поддержку нового синтаксиса из спецификации (display: flex;)
  • (hybrid) означает поддержку старого неофициального синтаксиса из 2011 (display: flexbox;)
  • (old) означает поддержку старого синтаксиса из 2009 (display: box;)
Chrome Safari Firefox Opera IE Android iOS
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);
}

Russian (Pусский) translation by Pembelight (you can also view the original English article)

Flexbox позволяет нам размещать флекс-элементы в любом порядке и направлении. Распределение порядка элементов с flexbox проще, чем с помощью float или CSS-сетки, даже если вы с этим не согласны.  Поскольку flexbox — это модель одномерного макета, в отличие от CSS-сетки, которая является двумерной, вам нужно обращать внимание только на одно направление.  W3C четко определелил правила, поэтому вам больше не придется иметь дело с float и clearfix.

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

  • flex-direction
  • flex-wrap
  • flex-flow
  • order 

Расстановка  Vs. Перестановка элементов 

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

Что такое расстановка?

Когда мы настраиваем макет flexbox, сначала нужно определить исходный порядок, то есть мы должны решить, как позиционируются оси flex контейнера. Я подробно описал flexbox оси в своем уроке по выравниванию flexbox.

Вкратце, каждый flex контейнер имеет две оси: главную и поперечную. Главная ось будет иметь одно из четырех направлений, а поперечная ось всегда перпендикулярна первой:

  1. слева направо
  2. справа налево
  3. сверху вниз
  4. снизу вверх

The cross axis is always perpendicular to the main axis The cross axis is always perpendicular to the main axis The cross axis is always perpendicular to the main axis

Поперечная ось всегда перпендикулярна к главной.

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

Так что же такое перестановка элементов?

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

Используя такие возможности flexbox, нам не приходится менять структуру HTML документа только ради его визуального отображения. Таким образом, скринридеры (и поисковые системы) считывают логически структурированный контент (например, боковая панель не имеет приоритета над основным контентом).

Свойство оrder для Flexbox

Порядок элементов во Flexbox происходит со свойствами flex-direction и flex-wrap: flex-direction указывает направление главной оси. Свойство  оrder может принимать следующие значения:

  1. row (по умолчанию) главной оси: слева направо
  2. row-reverse главной оси: справа налево
  3. column главной оси : сверху вниз
  4. column-reverse главной оси: снизу вверх

Flex-wrap определяет, расположены ли flex-элементы в один ряд или в несколько. Он также контролирует направление поперечной оси. Может иметь три значения:

  1. nowrap (по умолчанию) размещает flex-элементы в одну строку; поперечная ось стоит в положении по умолчанию
  2. wrap размещает  flex-элементы в несколько строк; поперечная ось стоит в положении по умолчанию
  3. wrap-reverse размещает  flex-элементы в несколько строк; поперечная ось в обратном порядке

Положение поперечной оси по умолчанию:

  • сверху вниз в случае row и row-reverse
  • слева направо в случае column и column-reverse

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

Пример шорткода

Мы используем простой код, чтобы увидеть, как работает flexbox расстановка элементов. В данном примере HTML состоит из нескольких элементов:

1
<div class="container">
2
      <div class="item item-1">1</div>
3
      <div class="item item-2">2</div>
4
      <div class="item item-3">3</div>
5
      <div class="item item-4">4</div>
6
      <div class="item item-5">5</div>
7
      <div class="item item-6">6</div>
8
      <div class="item item-7">7</div>
9
      <div class="item item-8">8</div>
10
      <div class="item item-9">9</div>
11
</div>

Элемент .container  div будет flex-контейнером, а div с классом .item будут flex-элементами. Мы будем использовать (почти) один и тот же CSS код во всех примерах, только поменяются свойства flex-direction и flex-wrap. Вот как выглядит наш CSS со значениями row и wrap:

1
html {
2
  background: #fff7f6;
3
}
4
.container {
5
  display: flex;
6
  flex-direction: row;
7
  flex-wrap: wrap;
8
}
9
.item {
10
  font-size: 2rem;
11
  line-height: 1;
12
  text-align: center;
13
  padding: 3rem;
14
  background: mistyrose;
15
  border: 3px solid tomato;
16
  color: tomato;
17
  margin: 6px;
18
}

Тот же пример в демонстрации на CodePen: 

Расстановка элементов с помощью Row и Column 

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

В подключенном ниже примере вы увидите, как макеты flex-direction: row и flex-direction: column взаимодействуют между собой с разными значениями свойства flex-wrap. Используйте выпадающие списки, чтобы увидеть их комбинации.

Как вы видите, когда flex-direction является row, flex-элементы располагаются горизонтально слева направо. Когда вместо wrap мы используем wrap-reverse, flexbox начинает выкладывать элементы снизу вверх, а не наоборот. Это происходит потому, что wrap-reverse меняет направление перпендикулярной оси.

Когда flex-direction это column, элементы располагаются вертикально сверху вниз. И когда мы используем wrap-reverse вместо wrap, flexbox начинает размещать элементы справа (теперь это начальная точка поперечной оси), а не слева.

Расстановка элементов с помощью row-reverse  и column-reverse 

Теперь давайте посмотрим на то, как flexbox размещает элементы, когда flex-direction — это row-reverse и column-reverse.

Как видно из демонстрации выше, в обоих случаях flexbox начинает выкладывать элементы, как и раньше, с начала по главной оси. Главная ось row-reverse проходит справа налево, поэтому flexbox начинает раскладывать элементы справа.  Кроме того, главная ось макета column-reverse проходит снизу вверх, поэтому элементы начинают размещаться снизу вверх flex контейнера.

Когда мы используем flex-wrap: wrap, flexbox начинает размещать элементы со свойством flex-direction: сверху row-reverse, и слева  column-reverse, так как они соответсвенно являются начальными точками поперечной оси.  

Когда мы меняем направление на flex-wrap: wrap-reverse, поперечная ось будет двигаться в противоположном направлении. Она будет размещать элементы при flex-direction снизу вверх row-reverse и справа налево при column-reverse.

Ускорьте процесс с помощью  flex-flow

Также значения flex-direction и flex-wrap могут применяться к одному классному CSS свойству. Оно называется flex-flow. Чтобы его использовать, нам нужно прописать эти два значения вместе, как это сделано ниже:

1
.container-1 {
2
    flex-flow: row wrap;
3
}
4
.container-2 {
5
    flex-flow: column-reverse wrap-reverse;
6
}

Перестановка элементов в Flexbox

Пришло время взглянуть на вещи немного по-другому.

Свойство order изменяет порядок по умолчанию для flex-элементов, который мы определяем с помощью flex-direction и flex-flow. Он влияет только на визуальное расположение элементов, но он не влияет на то, как скринридеры и другие пользовательские агенты, не относящиеся к CSS, читают исходный код.

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

В следующем примере .item-3 перемещается в начальную точку главной оси. Поскольку все элементы имеют значение по умолчанию 0, достаточно использовать правило order: -1, чтобы сделать его первым элементом в контейнере:

1
.item-3 {
2
    order: -1;   
3
}

Вы заметили, что эту же логику можно использовать для перемещения .item-3 к концу главной оси. Для этого нам только нужно назначить положительное значение свойства order.

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

1
.item-3 {
2
  order: -1;
3
}
4
.item-4 {
5
  order: -2;
6
}
7
.item-5 {
8
  order: 2;
9
}
10
.item-7 {
11
  order: 1;
12
}

Порядок и доступность

Самое важное — это то, что свойство order не влияет на порядок стилизации, контент и логическую навигацию элементов.  Это значит, что когда мы изменяем порядок наших flex элементов, невизуальные ползователи не заметят изменения. Например, люди, использующие навигацию с помощью клавиатуры, будут по-прежнему перемещаться по ссылкам в исходном порядке.

Такое поведение flexbox может пригодиться в некоторых случаях. Например, можно сделать так называемый «Макет Святого Грааля» доступным с помощью порядка во флексбоксе. Макет Святого Грааля — это популярный макет блога с хедером, футером и двумя боковыми сайдбарами: слева и справа от основного контента.

В HTML коде этого макета мы обычно ставим левый сайдбар перед основным содержимым. Однако с точки зрения доступности пользователи вспомогательных технологий должны в первую очередь знакомиться с основным контентом.   Flexbox с этим справляется идеально. В нашей разметке мы можем разместить основной контент перед двумя боковыми панелями. Затем нам остается только  правильно позиционировать сайдбар и основное содержимое, используя свойство order:

1
.sidebar-left { 
2
  order: 1;
3
}
4
article {
5
  order: 2;
6
}
7
.sidebar-right {
8
  order: 3;
9
}

Flexbox & Writing Modes

Все сказанное в этом уроке относится к режиму записи LTR (left to right — слева направо). Оси Flexbox фактически следуют направлению письма документа, которое можно настроить с помощью свойств direction и writing-mode. Вот почему в режиме записи LTR главная ось движется слева направо, когда flex-direction является row. В режиме записи RTL (right to left — справа налево) он работает в противоположном направлении, справа налево, и все остальное меняется соответственно.

Это (Flex) Wrap!

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

Узнайте больше

Понравилась статья? Поделить с друзьями:
  • Как изменить напольную плитку не снимая ее
  • Как изменить написать сообщение
  • Как изменить написанное на сайте
  • Как изменить написание ссылки
  • Как изменить написание букв на клавиатуре на телефоне