Основні концепції Флексбоксу

Модуль компонування гнучкої рамки (який зазвичай звуть флексбоксом) – це одновимірна модель компонування для розподілу простору між елементами, що пропонує чимало можливостей для вирівнювання. Ця стаття дає нарис основних можливостей флексбокса, котрі розглядаються більш докладно в інших посібниках.

Коли флексбокс описують як одновимірну систему, то мають на увазі, що він виконує розкладку в одному вимірі за раз – або в ряду, або в колонці. Це контрастує із двовимірною моделлю сіткової розкладки CSS, котра керує колонками та рядами водночас.

Дві осі флексбокса

При роботі із флексбоксом необхідно мислити поняттями двох осей: головної та поперечної. Головна вісь визначена властивістю flex-direction, а поперечна вісь – перпендикулярна до неї. Все, що виконується за допомогою флексбокса, використовує ці осі, тож варто розуміти їх суть з самого початку.

Головна вісь

Головна вісь визначається властивістю flex-direction, котра має чотири можливі значення:

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

Якщо обрати row або row-reverse, то головна вісь буде напрямлена горизонтально у рядковому напрямку.

Якщо flex-direction має значення row, то головна вісь напрямлена горизонтально у рядковому напрямку.

Якщо обрати column або column-reverse, то головна вісь буде напрямлена у блоковому напрямку, від верху сторінки до низу.

Якщо flex-direction має значення column, то головна вісь напрямлена вертикально у блоковому напрямку.

Поперечна вісь

Поперечна вісь напрямлена перпендикулярно до головної. Тож якщо flex-direction (головна вісь) має значення row або row-reverse, то поперечна вісь напрямлена вертикально.

Якщо flex-direction має значення row, то поперечна вісь напрямлена у блоковому напрямку.

Якщо головна вісь – column або column-reverse, то поперечна вісь напрямлена горизонтально.

Якщо flex-direction має значення column, то поперечна вісь напрямлена у рядковому напрямку.

Початкова та кінцева лінії

Іще одна життєво важлива для розуміння тема – те, як флексбокс не робить припущень щодо режиму письма документа. Флексбокс не робить припущень про те, що всі лінії тексту починаються у лівому верхньому куті документа і прямуватиме в бік правої руки, а наступні рядки з'являться знизу, один за одним. Замість цього він підтримує всі напрямки письма, подібно до інших логічних властивостей і значень.

Можна дізнатись більше про взаємини між флексбоксом та напрямками письма у пізнішій статті; втім, подальший опис повинен допомогти усвідомити, чому мова не йде про ліве та праве, про верх та низ, коли описуються напрями плину гнучких елементів.

Якщо значення flex-directionrow, а мова – українська, то початковий край головної осі буде зліва, а кінцевий край – справа.

При роботі з українською початковий край – зліва.

Якщо мова – арабська, то початковий край головної осі – справа, а кінцевий край – зліва.

Початковий край для мов, що мають запис справа наліво – справа.

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

З часом мислення категоріями початку та кінця замість ліва та права стає звичним, а це буде корисним при роботі з іншими способами розкладки, наприклад, із сітковою розкладкою CSS, котра має такі ж принципи.

Гнучкий контейнер

Область документа, скомпонована за допомогою флексбокса, називається гнучким контейнером. Щоб створити гнучкий контейнер, слід вказати для контейнера області властивість display зі значенням flex. Коли це зроблено, то безпосередні нащадки такого контейнера стають гнучкими елементами. Контролювати, чи відображається сам контейнер в контексті рядка, або ж в контексті блокового контексту форматування, можна за допомогою значень inline flex або inline-flex для рядкових гнучких контейнерів, і block flex або flex для гнучких контейнерів блокового рівня.

Початкові значення

Як і в випадку всіх інших властивостей CSS, існують певні визначені початкові значення, тож вміст нового гнучкого контейнера поводитиметься так:

  • Елементи виводяться в ряду (властивість flex-direction має усталене значення row).
  • Елементи починаються з початкового краю головної осі.
  • Елементи не розтягуються за головним виміром, але можуть скорочуватися (усталене значення властивості гнучкого елемента flex-grow0, а усталене значення його властивості flex-shrink1).
  • Елементи розтягуються, аби заповнити доступний простір за поперечною віссю (усталене значення властивості align-itemsstretch).
  • Властивість гнучкого елемента flex-basis має усталене значення auto. Це означає, що в кожному випадку вона буде рівною значенню width гнучкого елемента при горизонтальному письмі, або значенню height – при вертикальному письмі. Якщо відповідне значення width чи height також має значення auto, то використовується значення flex-basis content.
  • Усі елементи будуть в одному ряду (усталене значення властивості flex-wrapnowrap), переповнюючи свій контейнер, якщо їх сумарна ширина чи висота перевищує, відповідно, ширину чи висоту їх контейнера.

Як наслідок – елементи стануть в ряд, використовуючи розмір вмісту як свій розмір за головною віссю. Якщо елементів більше, ніж може вмістити контейнер, то вони будуть переповнювати його, а не перейдуть на наступний ряд. Якщо деякі елементи вищі за інших, то всі елементи будуть розтягнені за всією довжиною поперечної осі.

У живому зразку нижче видно, як це працює. Клацніть "Відтворити", аби відкрити цей приклад на Ігровому майданчику MDN та відредагувати елементи або додати нові, щоб спробувати початкову логіку флексбокса:

```html live-sample___the-flex-container
<div class="box">
  <div>Один</div>
  <div>Два</div>
  <div>Три <br />має <br />додатковий <br />текст</div>
</div>
.box > * {
  border: 2px solid rgb(96 139 168);
  border-radius: 5px;
  background-color: rgb(96 139 168 / 0.2);
}
.box {
  border: 2px dotted rgb(96 139 168);
  display: flex;
}

Зміна flex-direction

Властивість гнучкого контейнера flex-direction дає змогу змінити напрям виводу гнучких елементів. Встановлення flex-direction: row-reverse змусить елементи надалі виводитись в ряд, але змінить місцями початок та кінець ряду.

Якщо змінити значення flex-direction на column, то головна вісь перемкнеться, і елементи будуть виведені у стовпчик. Якщо задати column-reverse, то початок та кінець знову поміняються місцями.

У живому зразку нижче flex-direction має значення row-reverse. Спробуйте інші значення: row, column і column-reverse, – і погляньте, що станеться із вмістом.

<div class="box">
  <div>Один</div>
  <div>Два</div>
  <div>Три</div>
</div>
.box > * {
  border: 2px solid rgb(96 139 168);
  border-radius: 5px;
  background-color: rgb(96 139 168 / 0.2);
}

.box {
  border: 2px dotted rgb(96 139 168);
  display: flex;
  flex-direction: row-reverse;
}

Багаторядні гнучкі контейнери із flex-wrap

Хоч флексбокс і є одновимірною моделлю, можна змусити гнучкі елементи переходити на кілька рядів. Щоб це зробити, слід розглядати кожен ряд як новий гнучкий контейнер. Будь-який розподіл простору діятиме для кожного ряду окремо, без зв'язку з попередніми та наступними рядами.

Щоб ввімкнути переведення рядів, слід додати властивість flex-wrap зі значенням wrap. Після цього, якщо елементи завеликі, аби бути виведеними в одному ряду, вони будуть перенесені на наступний. Живий приклад нижче містить елементи зі заданою шириною, і сумарна ширина елементів завелика для гнучкого контейнера. Оскільки властивість flex-wrap має значення wrap, то елементи переходять на нові ряди. Якщо встановити значення nowrap, котре, до речі, є початковим, то елементи скоротяться, щоб вміститись у контейнері. Вони скоротяться, тому що мають початкові значення флексбокса, серед яких flex-shrink: 1, що дає елементам змогу скорочуватись. Використання nowrap призвело б до переповнення, якби елементи не могли скорочуватись, або якби не могли скоротитись настільки, щоб поміститися.

<div class="box">
  <div>Один</div>
  <div>Два</div>
  <div>Три</div>
</div>
.box > * {
  border: 2px solid rgb(96 139 168);
  border-radius: 5px;
  background-color: rgb(96 139 168 / 0.2);
  width: 200px;
}
.box {
  width: 500px;
  border: 2px dotted rgb(96 139 168);
  display: flex;
  flex-wrap: wrap;
}

Довідайтесь більше про перенесення гнучких елементів на новий ряд у настановах Опанування переведення гнучких елементів на новий ряд.

Скорочення flex-flow

Можна поєднати властивості flex-direction та flex-wrap у скороченні flex-flow.

У живому зразку нижче спробуйте змінити перше значення на одне з дозволених значень flex-direction - row, row-reverse, column чи column-reverse, а також змінити друге на wrap чи nowrap.

<div class="box">
  <div>Один</div>
  <div>Два</div>
  <div>Три</div>
</div>
.box > * {
  border: 2px solid rgb(96 139 168);
  border-radius: 5px;
  background-color: rgb(96 139 168 / 0.2);
  width: 200px;
}
.box {
  width: 500px;
  border: 2px dotted rgb(96 139 168);
  display: flex;
  flex-flow: row wrap;
}

Властивості, що застосовуються до гнучких елементів

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

Нижче – короткий позір на ці властивості, а повніший виклад інформації слід шукати в посібнику Керування співвідношеннями гнучких елементів за головною віссю.

Перед усвідомленням цих властивостей слід взяти до уваги концепцію доступного простору. При зміні значень цих гнучких властивостей – змінюється спосіб розподілу доступного простору між елементами. Ця концепція також важлива при вирівнюванні елементів.

Якщо є три 100-піксельні елементи у контейнері, що має ширину 500 пікселів, то простір, необхідний для розкладання елементів, – 300 пікселів. Це залишає 200 пікселів доступного простору. Якщо не змінити початкові значення, то флексбокс залишить цей простір вільним за останнім елементом.

Цей гнучкий контейнер має доступний простір після розкладання елементів.

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

Властивість flex-basis

flex-basis – те, що визначає розмір елемента щодо простору, який він залишає як доступний. Початкове значення цієї властивості – auto, – в такому випадку браузер перевіряє, чи має елемент розмір. У прикладі вище усі елементи мають ширину 100 пікселів. Це значення використовується як flex-basis.

Якщо елементи не мають ширини, то flex-basis отримує значення розміру вмісту. Саме тому коли на предку просто оголошено display: flex для створення гнучких елементів, то елементи стають в ряд і займають лише той простір, котрий потрібен їм для виводу свого вмісту.

Властивість flex-grow

Коли властивість flex-grow має значення додатного цілого числа і є доступний простір, гнучкий елемент може зростати за головною віссю понад свій flex-basis. Те, чи цей елемент розтягується для зайняття всього доступного простору на цій осі, чи лишень частку доступного простору, залежить від того, чи дозволено також рости іншим елементам і які значення в їхніх властивостей flex-grow.

Кожний елемент з додатним значенням з'їдає частку доступного простору, що залежить від його значення flex-grow. Якби всі елементи в прикладі вище мали значення flex-grow 1, то доступний простір у гнучкому контейнері був би порівну поділений між цими елементами, і вони розтягнулися б для заповнення контейнера за головною віссю. Якщо дати першому елементу значення flex-grow 2, а іншим елементам – кожному 1, то буде сумарно 4 частини; 2 частини доступного простору дістануться першому елементу (100px з 200px, коли мова про приклад вище), а по 1 частині – кожному з решти двох (50px кожному з 200px загалом).

Властивість flex-shrink

Коли властивість flex-grow займається додаванням простору за головною віссю, властивість flex-shrink керує її відбором. Якщо в контейнері немає достатнього простору для розкладання елементів, і flex-shrink має значення додатного цілого числа, то елемент стає меншим за flex-basis. Як і з flex-grow, різні значення можуть бути присвоєні, щоб один елемент скорочувався швидше за інших: елемент із більшим значенням flex-shrink скорочуватиметься швидше за братерні елементи із меншими значеннями.

Цей мінімальний розмір береться до уваги при роботі з дієвим розміром скорочення, тобто flex-shrink потенційно може здаватись менш послідовним у поведінці за flex-grow. Для більш детального розгляду того, як цей алгоритм працює, дивіться статтю Керування співвідношеннями гнучких елементів за головною віссю.

[!NOTE] Ці значення: flex-grow та flex-shrink – пропорції. Зазвичай якби усі елементи мали flex: 1 1 200px, а тоді хотіли, щоб один елемент зростав з подвійною швидкістю, то задали б йому flex: 2 1 200px. Втім, також за бажання можна було б використати flex: 10 1 200px чи flex: 20 1 200px.

Скорочені значення гнучких властивостей

Рідко можна побачити використання окремо властивостей flex-grow, flex-shrink і flex-basis; натомість їх поєднують у скорочення flex. Скорочення flex дає змогу встановити три значення у такому порядку: flex-grow, flex-shrink, flex-basis.

Живий зразок нижче дає змогу спробувати різні значення скорочення flex; пам'ятайте, що перше значення – flex-grow. Коли це значення – додатне, то це означає, що елемент може зростати. Друге значення – flex-shrink: із додатним значенням тут елементи можуть скорочуватись, втім, це може відбутись лише за умови, що сума розмірів елементів за головною віссю утворює переповнення. Останнє значення – flex-basis; це значення, котре елементи використовують як свій базовий розмір, від котрого відбувається зростання та скорочення.

<div class="box">
  <div class="one">Один</div>
  <div class="two">Два</div>
  <div class="three">Три</div>
</div>
.box > * {
  border: 2px solid rgb(96 139 168);
  border-radius: 5px;
  background-color: rgb(96 139 168 / 0.2);
}
.box {
  border: 2px dotted rgb(96 139 168);
  display: flex;
}
.one {
  flex: 1 1 auto;
}

.two {
  flex: 1 1 auto;
}
.three {
  flex: 1 1 auto;
}

Також є наперед визначені значення скорочення, що покривають більшість випадків. Їх часто можна побачити у настановах, і в багатьох випадках достатньо буде їх. Наперед визначені значення – наступні:

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

Значення initial – це глобальне значення, що представляє початкове значення властивості. Задання flex: initial скидає елемент до початкових значень всіх трьох властивостей-складових, і це те саме, що flex: 0 1 auto. Початкове значення flex-grow0, тож елементи не зростатимуть понад свій розмір flex-basis. Початкове значення flex-shrink1, тож елементи можуть скоротитись, якщо потрібно, замість переповнення контейнера. Початкове значення flex-basisauto. Елементи або скористаються якимось розміром, заданим для елемента за головною віссю, або отримають розмір на основі розміру вмісту.

Використання flex: auto – це саме, що flex: 1 1 auto; це схоже на flex: initial, але елементи можуть зростати та заповнювати контейнер, як і скоротитись, якщо потрібно.

Використання flex: none створить цілком негнучкі елементи гнучкого контейнера. Це еквівалентно до flex: 0 0 auto. Елементи не можуть зростати або скорочуватись, і будуть розкладені за допомогою флексбоксу зі значенням flex-basisauto.

Скорочений запис, котрий часто можна побачити у настановах: flex: 1, flex: 2, і так далі. Це те саме, що flex: 1 1 0 або, відповідно, flex: 2 1 0. Елементи можуть зростати та скорочуватись, маючи flex-basis зі значенням 0.

Спробуйте такі значення скороченого запису у живому зразку нижче.

<div class="box">
  <div class="one">Один</div>
  <div class="two">Два</div>
  <div class="three">Три</div>
</div>
.box > * {
  border: 2px solid rgb(96 139 168);
  border-radius: 5px;
  background-color: rgb(96 139 168 / 0.2);
}
.box {
  border: 2px dotted rgb(96 139 168);
  display: flex;
}
.one {
  flex: 1;
}
.two {
  flex: 1;
}
.three {
  flex: 1;
}

Вирівнювання та розподіл вільного простору між елементами

Ключова здібність флексбоксу – можливість вирівнювати елементи за головною та поперечною осями, а також розподіляти простір між гнучкими елементами. Зверніть увагу, що такі властивості мусять бути встановлені на гнучкому контейнері, а не на елементах.

align-items

Властивість align-items вирівнює всі гнучкі елементи на поперечній осі.

Початкове значення цієї властивості – stretch, і саме тому гнучкі елементи усталено розтягуються до висоти гнучкого контейнера (або ширини, якщо flex-direction має значення column або column-reverse). Така висота може бути продиктована висотою найвищого елемента у контейнері або розміром, заданим на самому контейнері.

Натомість можна задати align-items зі значенням flex-start, або просто start, аби елементи вишикувалися на початку гнучкого контейнера, flex-end або просто end – щоб вирівняти їх до кінця, або center – аби вирівняти їх по центру. Спробуйте це в живому зразку: я задав гнучкому контейнері висоту, аби ви могли побачити, як елементи можна рухати всередині контейнера. Подивіться, що відбудеться, якщо задати значення align-items:

  • stretch
  • flex-start
  • flex-end
  • start
  • end
  • center
  • baseline
  • last baseline
<div class="box">
  <div>Один</div>
  <div>Два</div>
  <div>Три <br />має <br />додатковий <br />текст</div>
</div>
.box > * {
  border: 2px solid rgb(96 139 168);
  border-radius: 5px;
  background-color: rgb(96 139 168 / 0.2);
}
.box {
  width: 500px;
  height: 130px;
  border: 2px dotted rgb(96 139 168);
  display: flex;
  align-items: flex-start;
}

Властивість align-items задана на гнучкому контейнері та впливає на всі гнучкі елементи. Якщо хочеться вирівняти один гнучкий елемент не так, як інші, можна задати на ньому align-self.

justify-content

Властивість justify-content використовується для вирівнювання елементів на головній осі, напрям якої встановлений властивістю flex-direction. Початкове значення – flex-start, що змушує елементи стати в початок контейнера, але можна також встановити значення flex-end, аби виставити їх у кінці, або center, щоб виставити у центрі.

Також можна використати значення space-between, аби захопити увесь незайнятий після розкладання елементів простір, і поділити його порівну між елементами так, щоб між кожними двома суміжними елементами був однаковий проміжок. Щоб зліва та справа (або, у разі колонок, – згори та знизу) від кожного елемента був однаковий простір, потрібно встановити значення space-around. З space-around же елементи отримують по половинці простору з обох боків. Іще можна змусити елементи мати однаковий простір навколо себе за допомогою значення space-evenly. З space-evenly елементи мають цілий однаковий простір з обох кінців.

Спробуйте наступні значення justify-content у живому зразку:

  • start
  • end
  • left
  • right
  • normal
  • flex-start
  • flex-end
  • center
  • space-around
  • space-between
  • space-evenly
  • stretch
<div class="box">
  <div>Один</div>
  <div>Два</div>
  <div>Три</div>
</div>
.box > * {
  border: 2px solid rgb(96 139 168);
  border-radius: 5px;
  background-color: rgb(96 139 168 / 0.2);
}
.box {
  border: 2px dotted rgb(96 139 168);
  display: flex;
  justify-content: flex-start;
}

Стаття Вирівнювання елементів у гнучкому контейнері більше заглиблюється в ці властивості, аби отримати краще розуміння їх роботи. Втім, у більшості випадків будуть корисними й наведені вище прості приклади.

justify-items

Властивість justify-items ігнорується при компонуванні гнучкого блока.

place-items і place-content

Властивість place-items – це властивість-скорочення для align-items і justify-items. Коли задати її на гнучкому контейнері, вона задає вирівнювання за головною, але не поперечною віссю, і justify-items у флексбоксі ігнорується. Є інша властивість-скорочення, place-content, яка визначає властивості align-content і justify-content. Властивість align-content впливає лише на гнучкі контейнери, що можуть загортатися на нові ряди, і про це мова йде у Вирівнюванні елементів у гнучкому контейнері.

Наступні кроки

Після прочитання цієї статті має сформуватись розуміння основних можливостей флексбоксу. У наступній статті розглядається те, як ця специфікація пов'язана з іншими частинами CSS.