Порядок следования flex-элементов (свойство flex-flow: flex-direction, flex-wrap) | Flexbox | CSS

Flexbox (флексбокс) предназначен для вёрстки гибких макетов. Ежели свойство display контейнера принимает значение flex, его прямые потомки становятся flex-элементами, порядком следования которых можно управлять с помощью свойств flex-flow и order.

flex-flow

1 — текст можно изменить
2 — текст можно изменить
3 — текст можно изменить
4 — текст можно изменить
<‘flex-direction’> || <‘flex-wrap’> flex-flow — это сокращённая запись двух свойств, значения по умолчанию которых:
  • flex-direction: row;
  • flex-wrap: nowrap;
row nowrap
наследует значение родителя
row nowrap
<style>
.raz {
  display: flex;
  flex-flow: row nowrap;
  max-height: 10em;
  border: 1px solid rgb(0, 180, 0);
  overflow: auto;
  background: green;
}
.raz div {
  padding: 1em;
  background: rgb(255, 255, 0);
}
.raz div:nth-child(2) {
  background: rgb(255, 225, 25);
}
.raz div:nth-child(3) {
  background: rgb(255, 200, 50);
}
.raz div:nth-child(4) {
  background: rgb(255, 175, 75);
}
</style>

<div class="raz">
  <div contenteditable>1 — текст можно изменить</div>
  <div contenteditable>2 — текст можно изменить</div>
  <div contenteditable>3 — текст можно изменить</div>
  <div contenteditable>4 — текст можно изменить</div>
</div>

Синтаксис:

/* одно значение */

/* row nowrap */
flex-flow: initial;

/* <‘flex-direction’> nowrap */
flex-flow: row;
flex-flow: row-reverse;
flex-flow: column;
flex-flow: column-reverse;

/* row <‘flex-wrap’> */
flex-flow: nowrap;
flex-flow: wrap;
flex-flow: wrap-reverse;

/* два значения */

/* <‘flex-direction’> <‘flex-wrap’> */
flex: column-reverse wrap-reverse;

flex-direction: направление flex-элементов

flex-элементы располагаются слева направо при direction: ltr; writing-mode: horizontal-tb;
flex-элементы располагаются справа налево при direction: ltr; writing-mode: horizontal-tb;
flex-элементы располагаются сверху вниз при direction: ltr; writing-mode: horizontal-tb;
flex-элементы располагаются снизу вверх при direction: ltr; writing-mode: horizontal-tb;
row
наследует значение родителя
row
<style>
.raz {
  display: flex;
  flex-direction: row;
  min-height: 15em;
  max-width: 15em;
  border: 1px solid rgb(0, 180, 0);
  overflow: auto;
  background: green;
}
.raz div {  /* если flex-элементы при column похожи на блочные, то при row их не стоит сравнивать со строчными */
  padding: 1em;
  background: rgb(255, 255, 0);
}
.raz div:nth-child(2) {
  background: rgb(255, 225, 25);
}
.raz div:nth-child(3) {
  background: rgb(255, 200, 50);
}
.raz div:nth-child(4) {
  background: rgb(255, 175, 75);
}
</style>

<div class="raz">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
</div>

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

direction writing-mode flex-direction
первый
второй
третий
<style>
.raz {
  display: flex;
  direction: ltr;
  writing-mode: horizontal-tb;
  flex-direction: row;
  width: 100%;
  min-height: 16em;
  border: 1px solid rgb(0, 180, 0);
  overflow: auto;
  background: green;
}
.raz div {
  padding: 1em;
  background: rgb(255, 255, 0);
}
.raz div:nth-child(2) {
  background: rgb(255, 225, 25);
}
.raz div:nth-child(3) {
  background: rgb(255, 200, 50);
}
</style>

<div class="raz">
  <div>первый</div>
  <div>второй</div>
  <div>третий</div>
</div>

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

Первый
  • Раз
  • Два
  • Три
  • Четыре
Второй
  • Раз
  • Два
Третий
  • Раз
  • Два
<style>
#raz {  /* блоки являются flex-элементами */
  display: flex;  /* блоки следуют друг за другом по горизонтали и имеют одинаковую высоту */
  overflow: auto;
}
#raz section {
  border: 1px solid #ccc;
  padding: .5em;
}
#raz section:not(:nth-of-type(3)) {  /* непосредственные потомки всех блоков, кроме третьего, являются flex-элементами */
  display: flex;
  flex-flow: column;  /* содержимое в блоках следует друг за другом по вертикали */
}
#raz button {
  margin-top: auto;  /* кнопка прижата к нижней границе блоков */
}
</style>

<section id="raz">
  <section>
    <h1>Первый</h1>
    <ul>
      <li>Раз
      <li>Два
      <li>Три
      <li>Четыре
    </ul>
    <button>Купить</button>
  </section>
  <section>
    <h1>Второй</h1>
    <ul>
      <li>Раз
      <li>Два
    </ul>
    <button>Купить</button>
  </section>
  <section>
    <h1>Третий</h1>
    <ul>
      <li>Раз
      <li>Два
    </ul>
    <button>Купить</button>
  </section>
</section>

Значения -reverse уместно применять, когда нужно изменить последовательность элементов, чтобы они шли в обратном порядке, например, переместить выше комментарии, оставленные недавно, или отсортировать строки по убыванию/возрастанию цены.

Телефон 15 000 ₽
Планшет 30 000 ₽
Стационарный компьютер 50 000 ₽
<style>
#raz5, 
#raz5 tbody {
  display: block;
  overflow: auto;
}
#raz5 tr {
  display: flex;
  border: 1px solid #ccc;
}
#raz5 td {
  display: block;
  flex: 1;
}
#raz5 td:nth-child(2) {
  flex: 0 0 5em;
}
#raz6:checked ~ #raz5 tbody {  /* без JS можно изменить очерёдность элементов (см. псевдокласс :checked) */
  display: flex;
  flex-flow: column-reverse;
}
</style>

<input id="raz6" type="checkbox"><label for="raz6"> <b>column-reverse</b></label>
<table id="raz5">
<tr>
  <td>Телефон
  <td>15 000 ₽
<tr>
  <td>Планшет
  <td>30 000 ₽
<tr>
  <td>Стационарный компьютер
  <td>50 000 ₽
</table>

Со значениями -reverse удобнее использовать :nth-last-child и :nth-last-of-type, так как псевдоклассы отталкиваются от положения элемента в HTML-коде.

1 2 3 4 5 6 7 8 9
<style>
#raz2 {
  display: inline-flex;
  flex-direction: row-reverse;
}
#raz2 b:nth-last-child(n+4) {
  color: red;
}
</style>

<div id="raz2"><b>1</b> <b>2</b> <b>3</b> <b>4</b> <b>5</b> <b>6</b> <b>7</b> <b>8</b> <b>9</b></div>

Значения row-reverse и column-reverse не только переворачивают flex-элементы задом наперёд, меняя их местами, но и при direction: ltr; writing-mode: horizontal-tb; прижимают их к правой или нижней границе flex-контейнера соответственно. Выровнять их можно с помощью свойства justify-content.

1
2
3
<style>
#raz1 {
  display: flex;
  flex-flow: column-reverse;
  justify-content: flex-end;
  min-height: 10em;
  border: 1px solid rgb(0, 180, 0);
  background: green;
}
#raz1 div {
  background: rgb(255, 255, 0);
}
#raz1 div:nth-child(2) {
  background: rgb(255, 225, 25);
}
#raz1 div:nth-child(3) {
  background: rgb(255, 200, 50);
}
</style>

<div id="raz1"><div>1</div><div>2</div><div>3</div><div>4</div></div>

flex-wrap: переход на другой ряд внутри flex-контейнера

1
2
3
4
элементы размещаются в одну линию
когда элемент не помещается в контейнер, он смещается в следующий ряд
когда элемент не помещается в контейнер, он смещается в предшествующий ряд
nowrap
наследует значение родителя
nowrap
<style>
.raz {
  display: flex;
  flex-wrap: nowrap;
  border: 1px solid rgb(0, 180, 0);
  background: green;
}
.raz div {
  width: 30%;
  padding: 1em;
  box-sizing: border-box;
  background: rgb(255, 255, 0);
}
.raz div:nth-child(2) {
  background: rgb(255, 225, 25);
}
.raz div:nth-child(3) {
  background: rgb(255, 200, 50);
}
.raz div:nth-child(4) {
  background: rgb(255, 175, 75);
}
</style>

<div class="raz">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
</div>

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

width overflow flex
1
2
3
<style>
.raz {
  display: flex;
  overflow: visible;
  border: 1px solid rgb(0, 180, 0);
  background: green;
}
.raz div {
  flex: 0 1 auto;
  width: 30%;
  background: rgb(255, 255, 0);
}
.raz div:nth-child(2) {
  background: rgb(255, 225, 25);
}
.raz div:nth-child(3) {
  background: rgb(255, 200, 50);
}
</style>

<div class="raz">
  <div>1</div>
  <div>2</div>
  <div>3</div>
</div>

Выбор между значениями wrap и wrap-reverse во многом зависит от сочетания со свойством flex-direction. Предусмотрены все варианты.

flex-direction flex-wrap
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<style>
.raz {
  display: flex;
  flex-flow: row wrap;
  width: 25em;
  height: 25em;
  border: 1px solid rgb(0, 180, 0);
  background: green;
}
.raz div {
  width: 25%;
  height: 25%;
}
</style>

<div class="raz">
  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
  <div>9</div>
  <div>10</div>
  <div>11</div>
  <div>12</div>
  <div>13</div>
  <div>14</div>
  <div>15</div>
  <div>16</div>
</div>

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

,
,
,
,

длина flex-контейнера:
???????????????????????????
???????????????????????????
<style>
.raz {
  display: flex;
  flex-flow: wrap;
  border: 1px solid rgb(0, 180, 0);
  background: green;
}
.raz div {
  min-width: 100px;
  max-width: 80px;
  width: 150px;  /* width/height не имеет смысла использовать с flex-basis */
  min-height: 2em;
  background: rgb(255, 255, 0);
}
.raz div:nth-child(2) {
  background: rgb(255, 225, 25);
}

/* flex-shrink и flex-grow совсем не оказывают никакого влияния на переход flex-элемента на другую линию */
#raz9 div {
  flex: 0 0 auto50px;
}
#raz10 div {
  flex: 1 1 auto50px;
}
</style>

<div class="raz" id="raz9">
  <div></div>
  <div>???????????????????????????</div>
</div>

<div class="raz" id="raz10">
  <div></div>
  <div>???????????????????????????</div>
</div>

При значениях wrap- доли от поначалу доступного пространства flex-контейнера, указанные в flex-grow, рассчитываются для каждого ряда индивидуально: когда flex-элемент остаётся один в ряду и его свойство flex-grow больше 0, а длина не ограничена max-width/max-height, он займёт всё доступное пространство в ряду (см. третий образец).

длина flex-контейнера: flex: 0 1 7em;
flex: 1 1 7em; max-width: 10em;
flex: 1 1 7em;
<style>
.raz {
  display: flex;
  flex-flow: wrap;
  border: 1px solid rgb(0, 180, 0);
  background: green;
}
.raz div {
  min-height: 2em;
  background: rgb(255, 255, 0);
}
.raz div:nth-child(2) {
  background: rgb(255, 225, 25);
}
.raz div:nth-child(3) {
  background: rgb(255, 200, 50);
}
#raz9 div {
  flex: 0 1 7em;
}
#raz10 div {
  flex: 1 1 7em;
  max-width: 10em;
}
#raz11 div {
  flex: 1 1 7em;
}
</style>

<div class="raz" id="raz9">
  <div></div>
  <div></div>
  <div></div>
</div>

<div class="raz" id="raz10">
  <div></div>
  <div></div>
  <div></div>
</div>

<div class="raz" id="raz11">
  <div></div>
  <div></div>
  <div></div>
</div>

При значениях wrap- свойство flex-shrink имеет смысл, только когда flex-элемент остаётся один в ряду, оно не распределяет доли и похоже на max-width: 100%;.

длина flex-контейнера:
111
222
333
111
222
333
<style>
#raz {
  flex-flow: wrap;
}
.raz {
  display: flex;
  border: 1px solid rgb(0, 180, 0);
  background: green;
}
.raz div {
  flex: 0 0 7em;
  background: rgb(255, 255, 0);
}
.raz div:nth-child(2) {
  flex: 0 1 7em;
  background: rgb(255, 225, 25);
}
.raz div:nth-child(3) {
  flex: 0 2 7em;
  background: rgb(255, 200, 50);
}
</style>

<div class="raz">
  <div>111</div>
  <div>222</div>
  <div>333</div>
</div>

<div class="raz" id="raz">
  <div>111</div>
  <div>222</div>
  <div>333</div>
</div>

При переполнении можно поменять значение свойства overflow у

  • flex-контейнера,
  • flex-элемента
длина flex-контейнера:
1111111111111111111
222
333
1111111111111111111
222
333
1111111111111111111
222
333
<style>
#raz,
#dva div:nth-child(1) {
  overflow: auto;
}
.raz {
  display: flex;
  flex-flow: wrap;
  border: 1px solid rgb(0, 180, 0);
  background: green;
}
.raz div {
  flex: 1 1 7em;
  background: rgb(255, 255, 0);
}
.raz div:nth-child(2) {
  background: rgb(255, 225, 25);
}
.raz div:nth-child(3) {
  background: rgb(255, 200, 50);
}
</style>

<div class="raz">
  <div>1111111111111111111</div>
  <div>222</div>
  <div>333</div>
</div>

<div class="raz" id="raz">
  <div>1111111111111111111</div>
  <div>222</div>
  <div>333</div>
</div>

<div class="raz" id="dva">
  <div>1111111111111111111</div>
  <div>222</div>
  <div>333</div>
</div>

Пример: меню с исчезающими при нехватки места пунктами

длина flex-контейнера:
menu
item1
item2
item3
<style>
.flex {
  display: flex;
  overflow: hidden;
  align-items: center;
}
.container {
  height: 2em;  /* фиксированная высота нужна, чтобы программе было ясно в каком месте нужно обрезать выходящие за границы элементы */
  flex-flow: row-reverse wrap-reverse;
  justify-content: center;
}
.item {
  flex: none;
  height: 100%;
}
.item.flex {
  flex: auto;
  width: 8em;  /* ширина, после которой синий пункт останется один */
  flex-wrap: wrap;
}
.item.flex .item {
  padding: 0 3em;
}
.yellow {
  background: yellow;
}
.orange {
  background: orange;
}
.red {
  background: red;
}
.blue {
  background: blue;
}
.green {
  background: green;
}
</style>

<div class="flex container">
    <div class="item blue">menu</div>
    <div class="item flex green">
        <div class="item yellow">item1</div>
        <div class="item orange">item2</div>
        <div class="item red">item3</div>
    </div>
</div>
в f t
наверх ↑

Комментариев нет: