Flexbox
Flexbox (flexible box, гнучкий блок) - новий підхід до розмітки блоків, який вдало поєднує табличне і блочне форматування.
Підтримка флексбоксів браузерами вже є достатньою, щоб застосовувати їх у комерційній верстці.
Бутстрап 4 для формування колонок використовує флексбокси замість флоатів.
Youtube: HTML Шорти - Кому потрібні флекси (5:13).
Напрямки потоків
Flexbox - набір стилів, які необхідно задавати як батьківським елементам, так і дочірнім.
Основа флексів - напрямок потоку. Блочні елементи розташовуються вертикально, строчні елементи - горизонтально, а флекс-елементам можна задавати напрямок розташування, в тому числі і зворотній: справа наліво, знизу вгору.
Батьківський елемент.
Поексперементуємо у jsFiddle:
ul>li{item $}*20
ul { margin:0; padding: 10px; list-style: none; border: 1px solid green; }
li { float: left; padding: 10px; background: #acf; border: 1px solid #aaa; }
В першу чергу створимо батьківський елемент, обгортку.
Можна використовувати будь-які теги (не порушуючи правила вкладень блочних та строчних елементів). В подальшому в прикладах коду вказані блоки div, але ми будемо працювати зі списком.
<div class="flex">
...
</div>
.flex { display: flex; }
// або
.flex { display: inline-flex; } // флекс-аналог inline-block
Ні для обгортки, ні для його дітей першого порядку не можна використовувати флоати та абсолютне чи фіксоване позиціонування (елементи автоматично отримують стиль display: block).
Далі задаємо напрямок розміщення дочірніх блоків. Є 4 варіанти напрямку:
.flex-row { flex-direction: row; }
.flex-wor { flex-direction: row-reverse; }
.flex-col { flex-direction: column; }
.flex-loc { flex-direction: column-reverse; }
<div class="flex flex-row">...</div>
<div class="flex flex-wor">...</div>
<div class="flex flex-col">...</div>
<div class="flex flex-loc">...</div>
row - горизонтальний напрямок потоку;
column - вертикальний напрямок потоку;
reverse - змінити напрямок розташування на протилежний.
При застосуванні вертикального напрямку решта стилів застосовується так, ніби блок повернений на 90 градусів проти часової стрілки, поверніть голову на бік :)
Можна вказати чи флекс-обгортка буде багатострочною, чи однострочною:
.flex { flex-wrap: nowrap; }
.flex { flex-wrap: wrap; }
.flex { flex-wrap: wrap-reverse; }
Значення стиля nowrap - всі блоки намагатимуться поміститися в одному рядку.
Значення стиля wrap - по досягненні кінця рядка блоки будуть переноситися на новий рядок.
Значення стиля wrap-reverse дозволяє змінити порядок рядків, перші елементи будуть знизу.
Попередні два стиля можна об'єднати одним:
.flex { flex-flow: row nowrap; }
.flex { flex-flow: column-reverse wrap; }
Розтягування контенту:
.flex { justify-content: flex-start; }
.flex { justify-content: flex-end; }
.flex { justify-content: center; }
.flex { justify-content: space-between; }
.flex { justify-content: space-around; }
Вирівнювання контенту по вертикалі:
.flex { align-items: flex-start; }
.flex { align-items: flex-end; }
.flex { align-items: center; }
.flex { align-items: stretch; }
.flex { align-items: baseline; }
Для багатострочного флекса є ще властивість, яка керує строками:
.flex { align-content: flex-start; }
.flex { align-content: flex-end; }
.flex { align-content: center; }
.flex { align-content: space-between; }
.flex { align-content: space-around; }
.flex { align-content: stretch; }
Дочірні елементи
Стиль, яким можна керувати порядком елементів:
.flex > div:nth-child(1) { order: 2; }
.flex > div:nth-child(2) { order: 3; }
.flex > div:nth-child(3) { order: 1; }
.flex > div:nth-child(4) { order: 4; }
Стиль, яким можна створити "сітку" з дочірніх елементів. Значення стилю - ціле чи дробне число більше нуля. Якщо задано нуль - блоки розтягуються відповідно іншим стилям.
Число - це пропорційне значення ширини блока.
.flex > div { flex-grow: 2; }
.flex > div:nth-child(2) { flex-grow: 2.5; }
.flex > div.long { flex-grow: 4; }
flex-shrink - стиль, що дає можливість стискатися елементу, числове значення, по замовчуванню - 1.
flex-basis - розмір елемента "по замовчуванню" до його розтягування відповідно стилів flex.
flex - стиль, що об'єднує в собі flex-grow, flex-shrink та flex-basis:
.flex > div { flex: 2 1 auto; }
align-self - дозволяє змінити стиль align-items батьківського елемента для конкретного дочірнього елемента:
.flex > div.end { align-self: flex-end; }
Шпаргалка по ширині дочірніх блоків
Властивість flex керує шириною дочірніх блоків (якщо задано колоночне розташування елементів - то висотою).
Ця властивість комбінована, складається з трьох параметрів:
flex: flex-grow flex-shrink flex-basis;
flex: 0 1 auto; // значення по-замовчуванню
Можна задавати одне або два значення. Будьте уважні, підставлятися можуть різні параметри, вдумливо ознайомтеся з наступним кодом:
flex: initial; // flex: 0 1 auto;
flex: none; // flex: 0 0 auto;
flex: auto; // flex: 1 1 auto;
flex: content; // flex: 1 1 content;
flex: 10px; // flex: 1 1 10px;
flex: 4; // flex: 4 1 0;
flex: 2 10px; // flex: 2 1 10px;
flex: 3 2; // flex: 3 2 0;
Швидка шпаргалка для основних випадків:
ширина = 150px
div {
flex: none;
width: 150px;
}
ширина <= 150px
div {
width: 150px;
}
ширина = 1/3 від залишку
div {
flex: 1;
}
ширина = 2/3 від залишку
div {
flex: 2;
}
Щоб зрозуміти різницю між першими двома блоками - спробуйте задати їм по-черзі ширину 100%. Перший буде займати рівно всю ширину блока і виштовхне сусідів вправо, другий - займе менше 100%, але доступний йому максимум.
У третьому та четвертому блоці цифри flex сумуються, сума приймається за 100%, і кожен блок буде займати вказану долю.
Наприклад, є 3 блока: два по боках фіксованого розміру, третій має займати всю ширину, що залишилася. Бокові будуть мати стиль { flex: none; width: ...px; } або ж взагалі ширина автоматично буде задаватися, а центральний - { width: 100%; }
Flex-basis
Параметр flex-basis визначає початкову, базову ширину елемента. Може приймати наступні значення:
flex-basis: auto; // ширина визначається автоматично
flex-basis: 100px; // ширина в px, %, em і т.д.
flex-basis: fill; // повна ширина флекс-батька
flex-basis: max-content; // по максимальній ширині контента
flex-basis: min-content; // по мінімальній ширині контента
flex-basis: fit-content; // підлаштовується під розмір контента
flex-basis: inherit; // наслідування від батьківського елемента
flex-basis: initial; // auto
flex-basis: unset; // auto
Частіше за все використовується значення auto, іноді - 0, решта значень досить рідкісні.
Якщо блоку задана властивість flex-basis не-auto, то значення стиля width (або height) для такого блока буде ігноруватися.
Якщо flex-basis: 0 - ширина блока вважається нульовою, далі реальна ширина розраховується через властивості flex-grow та flex-shrink.
Приклади мінімальної і максимальної ширини контента:
ipsum
dolorize
sit am lorem ipsum dolorize sit amen
Flex-grow
Принцип дії flex-grow та flex-shrink:
Сума ширин блоків < ширина флекс-обгортки — працює flex-grow.
Сума ширин блоків > ширина флекс-обгортки — працює flex-shrink.
Властивість flex-grow - доля від незайнятого простору флекс-обгортки. Може приймати такі значення:
flex-grow: 0; // ціле чи дробне число
flex-grow: 1.8;
flex-grow: initial; // значення по-замовчуванню flex-grow: 0;
flex-grow: inherit;
flex-grow: unset; // flex-grow: 0;
Розглянемо приклад. У нас є 2 блока шириною 100px і обгортка шириною 500px:
div { display: flex; }
<div>
<span class="box1"></span>
<span class="box2"></span>
</div>
У нас ширина всіх блоків = 200px, а ширина обгортки = 500px. Маємо вільні 300px.
Якщо задати обом блокам flex-grow: 1, то вони поділять вільний простір навпіл і кожен блок стане шириною 250px.
span { flex: 1 1 auto; }
span { flex: 5 1 auto; }
span { flex-grow: 1; } // скорочений варіант
Якщо ж задати їм різні значення, то вільний простір буде поділено між ними пропорційно:
.box1 { flex: 1 1 auto; } // 100 + 100 * 1 = 200px
.box2 { flex: 2 1 auto; } // 100 + 100 * 2 = 300px
// сума flex-grow = 3; 300px / 3 = 100px це ширина однієї долі
.box1 { flex-grow: 4; } // 100 + 54.5 * 4 = 318px
.box2 { flex-grow: 1.5; } // 100 + 54.5 * 1.5 = 182px
// сума flex-grow = 5.5; 300px / 5.5 = 54.5px це ширина однієї долі
.box1 { flex-grow: 0; } // 100 + 300 * 0 = 100px
.box2 { flex-grow: 1; } // 100 + 300 * 1 = 400px
// сума flex-grow = 1; 300px це ширина однієї долі
span { flex-grow: 0; } // ширина обох блоків залишиться 100px
Flex-shrink
Властивість flex-shrink діє подібно властивості flex-grow, але для надлишкової ширини (висоти) блоків і заставляє їх звузитися. Може приймати ті ж значення, що і flex-grow.
Нехай у нас в обгортці шириною 500px знаходяться три блока, ширина кожного з яких 220px. Маємо 220 * 3 - 500 = 160px надлишкових, тобто, останній блок в рядку буде виступати за межі обгортки на таку ширину.
div { display: flex; }
<div>
<span class="box1"></span>
<span class="box2"></span>
<span class="box3"></span>
</div>
При однакових значеннях flex-shrink у всіх блоків вони звузяться на 160 / 3 = 53px. При різних - буде вираховано пропорцією:
span { flex-shrink: 1; } // 220 - 53 * 1 = 167px
span { flex: 0 2.5 auto; } // 220 - 21 * 2.5 = 167px
// сума частин буде 3 і 7.5; 160 / 3 = 53px і 160 / 7.5 = 21px
.box1 { flex-shrink: 1; } // 220 - 40 * 1 = 180px
.box1 { flex-shrink: 0; } // 220 - 40 * 0 = 220px
.box1 { flex-shrink: 3; } // 220 - 40 * 3 = 100px
// сума частин буде 4; 160 / 4 = 40px
Домашнє завдання.
- Спробуйте зверстати проект Minecraft флексами.
Визуальное руководство по свойствам Flexbox.
Flexbox adventures (песочница флексбоксов).