Flexbox (флексбокс) предназначен для вёрстки гибких макетов. Ежели свойство display контейнера принимает значение flex, его прямые потомки становятся flex-элементами, порядком следования которых можно управлять с помощью свойств flex-flow и order.
flex-flow
|
1 — текст можно изменить
2 — текст можно изменить
3 — текст можно изменить
4 — текст можно изменить
| ||
<‘flex-direction’>
|| <‘flex-wrap’>
| flex-flow — это сокращённая запись двух свойств, значения по умолчанию которых:
| |
|---|---|---|
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 пока не использовать для флексбокса.
<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-коде.
<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.
<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).
<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. Предусмотрены все варианты.
<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: 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%;.
<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-элемента
<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>
Пример: меню с исчезающими при нехватки места пунктами
<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>
Комментариев нет: