Що таке Flexbox? Опис усіх CSS властивостей, основні принципи, переваги та недоліки

  • 1139
  • 2
  • 16 березня, 2023
  • читати 15 хв

Зміст

Flexbox можна назвати вдалою спробою вирішення величезного спектра проблем при побудові лейаутів в CSS. Але перш ніж перейти до його опису, давайте з'ясуємо, що не так зі способами верстки, якими ми користуємося зараз?

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

Сталося так тому, що HTML та CSS розвивалися еволюційно. На початку веб-сторінки були схожі на однопотокові текстові документи, згодом розбиття сторінки на блоки робили таблицями, потім стало модним верстати float-ами, а після офіційної смерті IE6 додалися ще й прийоми з inline-block. У результаті ми отримали у спадок гримучу суміш усіх цих прийомів, використовувану для побудови лейаутів 99,9% всіх існуючих веб-сторінок.

Специфікація CSS Flexible Box Layout Module (у народі — Flexbox) покликана кардинально змінити ситуацію на краще при вирішенні величезної кількості завдань. Flexbox дозволяє контролювати розмір, порядок та вирівнювання елементів по кількох осях, розподіл вільного місця між елементами та багато іншого.

Основні переваги Flexbox

  1. Всі блоки дуже легко робляться «гумовими», що вже випливає з назви «Flex». Елементи можуть стискатися та розтягуватися за заданими правилами, займаючи потрібний простір.
  2. Вирівнювання по вертикалі та горизонталі, базової лінії тексту працює шикарно.
  3. Розташування елементів HTML не має вирішального значення. Його можна змінити в CSS. Це особливо важливо для деяких аспектів Responsive верстки.
  4. Елементи можуть автоматично вишиковуватися в кілька рядків/стовпців, займаючи все надане місце.
  5. Безліч мов у світі використовують написання праворуч ліворуч rtl (right-to-left), на відміну від звичного нам ltr (left-to-right). Flexbox пристосований для цього. У ньому є поняття початку та кінця, а не права та ліва. Тобто у браузерах з локаллю rtl всі елементи будуть автоматично розміщені у реверсному порядку.
  6. Синтаксис CSS правил дуже простий та опановується досить швидко.

Підтримка браузерами

Підтримка браузерами поки що неповна (2014). Винен у цьому переважно Internet Explorer, який підтримує специфікацію 2011 року лише починаючи з 10 версії.

Незважаючи на це, зверніть увагу на широку підтримку всіма іншими мобільними та десктопними браузерами! Тут все чудово.

Flexbox — один із способів, яким чином досягається кросбраузерність сайту. Якщо вам потрібна мобільна версія сайту або web-based додаток, його вже можна (а, можливо, і потрібно) робити, використовуючи всі переваги Flexbox!

Починаємо занурення

Flexbox визначає набір CSS властивостей для контейнера (flex-контейнер) та його дочірніх елементів (flex-блоків).

Перше, що потрібно зробити, — вказати контейнеру display:flex або display:inline-flex.

<div class="my-flex-container">
  <div class="my-flex-block">item1</div>
  <div class="my-flex-block">item2</div>
  <div class="my-flex-block">item3</div>
</div>
.my-flex-container{
  display: flex;
}

Основні характеристики Flex-контейнера. Головна та поперечна вісь

Одним з основних понять у Fleхbox є осі.

  • Головною віссю Flex-контейнера є напрям, відповідно до якого розташовуються всі його дочірні елементи.
  • Поперечною віссю називається напрямок, перпендикулярний головній осі.

Головна вісь в ltr локалі за умовчанням розташовується зліва направо. Поперечна — зверху вниз. Напрямок головної осі Flex-контейнера можна задавати за допомогою базової CSS властивості flex-direction.

flex-direction — напрямок головної осі

Доступні значення flex-direction:

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

justify-content — вирівнювання за головною віссю

CSS властивість justify-content визначає те, як вирівняні елементи вздовж головної осі.

Доступні значення justify-content:

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

align-items — вирівнювання по поперечній осі

CSS властивість align-items визначає те, як вирівняні елементи вздовж поперечної осі.

Доступні значення align-items:

  • flex-start: блоки притиснуті до початку поперечної осі
  • flex-end: блоки притиснуті до кінця поперечної осі
  • center: блоки розташовані в центрі поперечної осі
  • baseline: блоки вирівняні за їх baseline
  • stretch (значення за замовчуванням): блоки розтягнуті, займаючи все доступне місце по поперечній осі, при цьому все ж таки враховуються min-width/max-width, якщо такі задані.

СSS властивості flex-direction, justify-content, align-items повинні застосовуватися безпосередньо до flex-контейнеру, а не до його дочірніх елементів.

Багаторядкова організація блоків усередині Flex-контейнера

flex-wrap

Всі приклади, які ми наводили вище, були побудовані з урахуванням однорядкового (одностовбцевого) розташування блоків. Треба сказати, що за замовчуванням Flex-контейнер завжди розташовуватиме блоки всередині себе в одну лінію. Проте специфікацією також підтримується багаторядковий режим. За багаторядковість усередині flex-контейнера відповідає CSS властивість flex-wrap.

Доступні значення flex-wrap:

  • nowrap (значення за промовчанням): блоки розташовані в одну лінію зліва направо (в rtl справа наліво)
  • wrap: блоки розташовані в кілька горизонтальних рядів (якщо не вміщуються в один ряд). Вони йдуть один за одним зліва направо (в rtl справа наліво)
  • wrap-reverse: те саме, що і wrap, але блоки розташовуються у зворотному порядку.

flex-flow — зручне скорочення для flex-direction + flex-wrap

По суті, flex-flow дає можливість в одній властивості описати напрямок головної та багаторядковість поперечної осі. За промовчанням flex-flow: row nowrap.

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

/* тобто ... */

.my-flex-block{
  flex-direcrion:column;
  flex-wrap: wrap;
}

/* це те ж саме, що ... */

.my-flex-block{
  flex-flow: column wrap;
}

align-content

Існує також властивість align-content, яка визначає те, яким чином ряди блоків, що утворилися, будуть вирівняні по вертикалі і як вони поділять між собою весь простір Flex-контейнера.

Важливо: align-content працює тільки в багаторядковому режимі (тобто у випадку flex-wrap:wrap; або flex-wrap:wrap-reverse;)

Доступні значення align-content:

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

CSS властивості flex-wrap та align-content повинні застосовуватися безпосередньо до flex-контейнера, а не до його дочірніх елементів.

CSS правила для дочірніх елементів flex-контейнера (flex-блоків)

flex-basis — базовий розмір окремо взятого flex-блоку

Задає початковий розмір головної осі для flex-блоку до того, як до нього будуть застосовані перетворення, засновані на інших flex-факторах. Може бути заданий у будь-яких одиницях виміру довжини (px, em, %, …) або auto (за замовчуванням). Якщо задано як auto — за основу беруться розміри блоку (width, height), які можуть залежати від розміру контенту, якщо не вказані явно.

flex-grow — «жадібність» окремо взятого flex-блоку

Визначає те, наскільки окремий flex-блок може бути більшим за сусідні елементи, якщо це необхідно.

flex-grow набуває безрозмірного значення ( за замовчуванням 0)

Приклад 1:

  • Якщо всі flex-блоки всередині flex-контейнера мають flex-grow:1, то вони будуть однакового розміру
  • Якщо один з них має flex-grow:2, то він буде в 2 рази більше, ніж усі інші

Приклад 2:

  • Якщо всі flex-блоки всередині flex-контейнера мають flex-grow:3, то вони будуть однакового розміру
  • Якщо один з них має flex-grow:12, то він буде вчетверо більше, ніж усі інші

Тобто абсолютне значення flex-grow не визначає точну ширину. Воно визначає його ступінь «жадібності» по відношенню до інших flex-блоків того ж рівня.

flex-shrink — фактор «стискання» окремо взятого flex-блоку

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

flex — короткий запис для властивостей flex-grow, flex-shrink та flex-basis

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

/* тобто ... */

.my-flex-block{
  flex-grow:12;
  flex-shrink:3;
  flex basis: 30em;
}

/* це те ж саме, що ... */

.my-flex-block{
  flex: 12 3 30em;
}

align-self — вирівнювання окремо взятого flex-блоку по поперечній осі

Уможливлює перевизначення властивості flex-контейнера align-items для окремого flex-блоку.

Доступні значення align-self (ті ж 5 варіантів, що й для align-items)

  • flex-start: flex-блок притиснутий до початку поперечної осі
  • flex-end: flex-блок притиснутий до кінця поперечної осі
  • center: flex-блок розташовуються в центрі поперечної осі
  • baseline: flex-блок вирівняний за baseline
  • stretch (значення за замовчуванням): flex-блок розтягнутий, щоб зайняти все доступне місце по поперечній осі, при цьому враховуються min-width/max-width, якщо такі задані.

order — порядок проходження окремо взятого Flex-блоку всередині Flex-контейнера

За замовчуванням всі блоки будуть йти один за одним у порядку, заданому в HTML. Однак цей порядок можна змінити за допомогою властивості order. Воно задається цілим числом і за умовчанням 0.

Значення order не визначає абсолютну позицію елемента в послідовності. Воно визначає вагу позиції елемента.

<div class="my-flex-container">
  <div class="my-flex-block" style="order: 5" >item1</div>
  <div class="my-flex-block" style="order: 10">item2</div>
  <div class="my-flex-block" style="order: 5" >item3</div>
  <div class="my-flex-block" style="order: 5" >item4</div>
  <div class="my-flex-block" style="order: 0" >item5</div>
</div>

В даному випадку, блоки будуть йти один за одним уздовж головної осі в наступному порядку: item5, item1, item3, item4, item2.

margin: auto — по вертикалі. Мрії збуваються!

Flexbox можна любити хоча б за те, що звичне для всіх вирівнювання по горизонталі через margin:auto тут працює і для вертикалі!

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

.my-flex-block {
  width: 100px;  /* Або що завгодно */
  height: 100px; /* Або що завгодно */
  margin: auto;  /* Магія! Блок відцентрований по вертикалі та горизонталі! */
}

Речі, які слід пам'ятати

  • Не слід використовувати Flexbox там, де в цьому немає потреби.
  • Визначення регіонів і зміна порядку контенту у багатьох випадках корисно робити залежним від структури сторінки. Продумуйте це.
  • Розберіться у Flexbox та знайте його основи. Так набагато легше досягти очікуваного результату.
  • Не забувайте про margin-и. Вони враховуються при встановленні вирівнювання по осях. Також важливо пам'ятати, що margin-и у Flexbox не “колапсяться”, як це відбувається у звичайному потоці.
  • Значення float у Flex-блоків не враховується та не має значення. Це, мабуть, якось можна використовувати для graceful degradation під час переходу на Flexbox.
  • Flexbox дуже добре підходить для верстки веб-компонентів та окремих частин веб-сторінок, але показав себе не з кращого боку при верстці базових макетів (розташування article, header, footer, navbar тощо).