Будуємо з Flexbox

21

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

Будуємо з FlexboxБудуємо з Flexbox

Введення

Деякий час тому я написав ознайомчу статтю про flexbox на сайті SitePoint. У даній статті я постарався з’ясувати і відповісти на питання: А чи готові ми використовувати flexbox?

Минулого разу я говорив, що вам слід дуже акуратно використовувати дану можливість, але наполягав на тому, що потрібно обов’язково познайомитися з її синтаксисом і впроваджувати її в сучасні проекти. Зараз я радий, що можу дати позитивну відповідь на своє питання: Так, ми готові використовувати flexbox!

Якщо ви ще не знайомі з flexbox (флексбокс), то ось невелике пояснення. CSS модуль побудови гнучкої розмітки — це розмічальний модуль, що дозволяє легко розміщувати блоки на екрані, в межах виділеного простору. Це велике досягнення у порівнянні з класичною блокової моделлю, т. к. флексбокс дозволяє взагалі не використовувати властивість float. Блоки (бокси) можуть бути об’єднані в рядки або розбиті на колонки. Для кожного флексбокс-елемента може бути заданий певний порядок. А також можна одразу керувати вирівнюванням, відступами і розмірів цих елементів.

Мабуть, що у даній статті мені не вдасться розглянути всі аспекти даного модуля, тому я пропоную вам познайомитися з ним детальніше, перейшовши за вищезазначеним посиланням на сайт MDN. А в даній навчальній статті ви розглянемо найпоширеніші проблеми з розміткою і побачимо, як легко і швидко їх можна вирішити. Кожен шаблон розмітки, про який я розповім, чуйним, що ще більше підкреслить ту легкість, з якою можна створювати розмітку за допомогою флексбокс. Ось що ми розглянемо:

Проста сіткова система

Розмітка Священного Грааля

Гумова навігація зі змінною шириною поля пошуку

Два різних варіанти вертикального вирівнювання

Добре, давайте приступати

1 — Проста сіткова система

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

1
2

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

1
2
1
2
3
1
2
3
4

А тепер давайте подивимося на CSS код. Деякі властивості я використовував суто в естетичних цілях (наприклад, межі і внутрішні відступи), а в іншому все дуже просто:

.grid {
border: solid 1px #e7e7e7;
}
.grid__row {
display: flex;
}
.grid__item {
flex: 1;
padding: 12px;
border: solid 1px #e7e7e7;
}

Ось як-то так! І наша сітка вже готова до використання. Додаючи display: flex до контейнерів .grid__row, ми створюємо, так званий, флекс-контейнер, а кожний дочірній елемент у контейнері відразу стає флекс-елементом. Застосовуючи властивість flex: 1 до флекс-елементів, ми змушуємо їх займати рівну кількість місця щодо загальної ширини контейнера. Тепер у вас може бути скільки завгодно рядків у сітці, а в кожній з них може бути свій власний кількість мережевих елементів. І це буде проста повністю чуйна сіткова система без всякого додаткового CSS.

А що можна сказати щодо брейкпойнтов (контрольних точок) і колонковою розмітки? Якщо ми хочемо, щоб елементи сітки шикувалися в колонки, а не в рядки, то ми можемо просто оголосити властивість flex-direction: column для контейнерів з класом .grid__row. В цьому випадку ми можемо створити дуже просту чуйну сітку, внісши деякі зміни. І наша розмітка буде виглядати ось так:

1

1

1

А наш CSS ось так:

.grid {
border: solid 1px #e7e7e7;
}
.grid__row {
display: flex;
flex-direction: column;
}
.grid__item {
flex: 1;
padding: 12px;
border: solid 1px #e7e7e7;
}
@all media and ( min-width: 480px ) {
.grid__row—sm {
flex-direction: row;
}
}
@all media and ( min-width: 720px ) {
.grid__row—md {
flex-direction: row;
}
}
@all media and ( min-width: 960px ) {
.grid__row—lg {
flex-direction: row;
}
}

І вуаля. Супер-проста чуйна сіткова система завдовжки всього кілька CSS рядків. Ця система настільки непробивна, що ви навіть можете вкладати сітки один в одного, не піклуючись про наслідки:

Nested 1

2
1

Подивитеся на це в дії.

2 — Розмітка Священного Грааля

Розмітка Священного Грааля є досить відомою у веб-дизайні, і навіть в епоху веб-додатків і всього іншого веселощів, даний варіант розмітки і раніше відіграє важливу роль в вебі — така розмітка постійно використовується на сайтах, у яких багато контенту. Ще в 2006 році розмітка Священного Грааля була чудово розібрана і описана на сайті A List Apart. В ній використовуються плаваючі елементи (властивість float), негативні зовнішні відступи (властивість margin) і мінімальні значення ширини (властивість min-width), щоб суміщені розміри елементів не конфліктували один з одним і не ламали розмітку. І все це, з урахуванням нинішньої необхідності у створенні чуйною розмітки, означало використання великої кількості обчислень, скасування обтікання та інших трюків, щоб це все працювало правильно. І якщо ви вирішили поміняти ширину бічної колонки (сайдбара), то потрібно було заново робити всі обчислення.

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

В моєму демо-прикладі розмітка Священного Грааля знаходиться всередині документа, тому в ній немає тегів body або main, як це показано вище. Тим не менш, ми зацікавлені в іменах класів і появі розділів у нашій розмітці на відміну від безпосередньо самих елементів. Зокрема, зверніть увагу на класи-модифікатори, які використовуються для двох бічних колонок, і на той порядок, в якому вони слідують у розмітці. Давайте послідовно розглянемо, що тут відбувається:

У нас є батьківського контейнера .holy-grail, а в ньому у нас знаходиться три флекс-елемента. Це елементи з класами .holy-grail__header, holy-grail__body і holy-grail__footer.

Дані три елементи розташовані один над одним і займають 100% від ширини екрана. Таким чином, для флекс-контейнера повинно бути задано колоночное напрямок.

Тіло нашої розмітки .holy-grail__body, є внутрішнім флекс-контейнером. Його дочірні флекс-елементи повинні мати колонкову розмітку на невеликих екранах і рядкову розмітку на широких екранах.

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

.holy-grail {
display: flex;
flex-direction: column;
}
.holy-grail__header,
.holy-grail__footer {
flex: 0 0 100%;
}
.holy-grail__body {
display: flex;
}
.holy-grail__sidebar {
/* нічого на невеликих екранах */
}
.holy-grail__sidebar—first {
order: 1;
}
.holy-grail__sidebar—second {
order: 3;
}
.holy-grail__content {
order: 2;
}
@all media and ( min-width: 720px ) {
.holy-grail__body {
flex-direction: row;
}
.holy-grail__sidebar {
flex: 0 0 180px;
}
.holy-grail__content {
flex: 1;
}
}
@all media and ( min-width: 960px ) {
.holy-grail__sidebar {
flex: 0 0 240px;
}
}

Це дійсно настільки просто! Як я вже згадував, ми спочатку визначаємо два флекс-контейнера (для невеликих екранів). Для першої контрольної точки, ми змінюємо флекс-напрям у тіла розмітки на рядкове, а бічних колонках задаємо ширину 180px, використовуючи скорочену запис — властивість flex. Дана запис дозволить нам обмежити значення для властивостей flex-grow і flex-shrink, а також явно вказати ширину. Для контенту використовується властивість flex: 1, щоб він заповнював доступне простір. Розташування флекс-елементів в потрібному порядку також виявилося дрібницею завдяки властивості order. Мабуть, залишилися тільки додаткові стилі, які ви захочете додати з естетичної точки зору… а в іншому це дійсно просто і ефективно. А згадав я про те, що за замовчуванням флексбокс створює колонки однакової висоти?

Погляньте на цей демо-приклад.

3 — Гумова навігація зі змінною шириною поля пошуку

У нашому прикладі ми будемо створювати щось веселе, що включає красивий перехід. Ми створимо гумову навігацію, яка розтягується на всю ширину, а в ній ми розмістимо поле пошуку, яке буде плавно розтягуватися в стані фокуса. Використовуючи силу флексбокса, ми зможемо додати стільки пунктів меню, скільки захочемо, не змінюючи при цьому CSS. Я буду використовувати деякі класи-модифікатори для досягнення потрібного результату. Як невеликий бонус я збираюся зробити нашу навігацію повністю чуйною, додавши для неї кнопку-перемикач! Ось як буде виглядати HTML:

Toggle Nav

  • Item 1
  • Item 2
  • Item 3
  • Item 4

Давайте розберемо цю розмітку, перш ніж ми перейдемо до CSS. У нас є основний флекс-контейнер з класом .flexy-nav. Кнопка використовується в якості перемикача, в ненумерованном списку містяться пункти основного меню, а в формі міститься поле пошуку. Для невеликих екранів нам потрібно використовувати колонкову розмітку для всіх трьох елементів, а також нам потрібно, щоб кожен пункт меню розташовувався в окремій колонці. На широких екранах нам потрібно сховати кнопку-перемикач, вибудувати елементи списку в рядок і вибрати для форми фіксовану ширину. Елементи списку будуть рівномірно розподілені серед решти простору. Коли ми перемикаємося на текстове поле (поле пошуку), нам би хотілося, щоб воно плавно розтягувалося по ширині, а всі елементи списку, навпаки, плавно звужувалися. Ось CSS:

/* скидання стилів */
input,
button {
font: inherit;
border-radius: none;
box-shadow: none;
appearance: none;
}
button {
cursor: pointer;
}
/* контейнер навігації */
.flexy-nav {
display: flex;
flex-direction: column;
}
/* пункти меню */
.flexy-nav__items {
display: none;
flex: 1;
flex-direction: column;
list-style: none;
margin: 0 0 4px 0;
padding: 4px;
text-align: center;
}
.flexy-nav__items—visible {
display: flex;
}
.flexy-nav__item {
background-color: #f1f1f1;
border-bottom: solid 1px #e7e7e7;
}
.flexy-nav__item:last-child {
border-bottom: 0;
}
.flexy-nav__link {
padding: 8px;
display: block;
}
/* перемикач меню */
.flexy-nav__toggle {
margin: 0 0 4px 0;
padding: 4px;
color: #fff;
background-color: #f07850;
border: none;
}
.flexy-nav__toggle:hover,
.flexy-nav__toggle:focus {
outline: none;
background-color: #c93f11;
}
/* форма для поля пошуку в навігації */
.flexy-nav__form {
height: 48px;
}
.flexy-nav__search {
display: block;
margin: 0;
padding: 0 4px;
width: 100%;
height: 48px;
color: #6d6d6d;
background-color: #fff;
border: 2px solid #e7e7e7;
}
.flexy-nav__search:focus {
outline: none;
border: 2px solid #6d6d6d;
}
/* медіа-запитів */
@all media and (min-width: 768px) {
.flexy-nav {
flex-direction: row;
}
.flexy-nav__items {
display: flex;
flex-direction: row;
margin: 0;
padding: 0;
height: 48px;
}
.flexy-nav__item {
flex: 1;
margin-right: 4px;
border-bottom: none;
}
.flexy-nav__link {
padding: 0;
line-height: 48px;
}
.flexy-nav__toggle {
display: none;
}
.flexy-nav__form {
flex: none;
}
.flexy-nav__search {
width: 240px;
transition: width 0.3 s;
}
.flexy-nav__search:focus {
width: 360px;
}
}

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

(function() {
var toggle = document.querySelector(«#flexy-nav__toggle»);
var nav = document.querySelector(«#flexy-nav__items»);
toggle.addEventListener. («click», function(e) {
e.preventDefault();
nav.classList.contains(«flexy-nav__items—visible») ? nav.classList.remove(«flexy-nav__items—visible») : nav.classList.add(«flexy-nav__items—visible»);
});
})();

Настільки все просто. Ми тільки що створили красиву і масштабовану гумову навігацію за допомогою флексбокс, а також вбудували плавний перехід при зміні ширини у поле пошуку. Ми можемо скільки завгодно додавати або видаляти посилання, а також «на льоту» змінювати розміри поля пошуку. І при цьому функціональність нашого меню анітрошки не постраждає. Ах, ось вони принади флексбокса. Не забудьте подивитися відповідний демо-приклад.

4 — Вертикальне вирівнювання

Давайте визнаємо той факт, що вертикальне вирівнювання в традиційному CSS просто нікуди не годиться. Терміново-блокові елементи можуть іноді з цим допомогти, є також хакі з абсолютним позиціонуванням, а ще є застарілі табличні розмітки (які на даний момент неприйнятні для багатьох випадків з семантичної точки зору). У всіх цих способів є свої особливості, і вони точно зажадають від вас додаткових «танців з бубнов», щоб все працювало як треба.

Флексбокс з легкістю візьме це на себе. Ми розглянемо два приклади вертикального вирівнювання:

Спочатку ми розглянемо створення, так званого, «медіа-об’єкт», в якому використовується інтерфейс аватар (ліворуч) і ім’я користувача + деяка інформація (розташовані праворуч). Ми будемо використовувати флексбокс, щоб зображення і тіло медіа-об’єкта були ідеально вирівняні по вертикалі.

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

Давайте почнемо з першого прикладу. Як вже було сказано, нам потрібно розташувати користувальницький аватар зліва, а опис — праворуч. І неважливо наскільки довгим або коротким буде опис. Нам потрібно, щоб воно завжди було ідеально вирівняний з аватаром. Ось стандартна розмітка:

John Doe

I’m John Doe…

Harry Potter

I’m Harry Potter…with a really long description…

Перш ніж ми перейдемо до CSS, зверніть увагу на те, що ми будемо використовувати незнайоме до цього властивість. Це властивість align-items, і воно дозволяє нам вирівнювати елементи уздовж, так званої, флекс-лінії в перпендикулярному напрямку. Іншими словами, якщо наша флекс-лінія розташована горизонтально, то ми можемо вирівнювати наші елементи в напрямку, перпендикулярно до цієї лінії. В нашому випадку нам потрібно вирівняти елементи по центру, тому ми будемо використовувати значення align-items: center. Ось CSS:

.user {
display: flex;
align-items: center;
}
.user:last-child {
margin-bottom: 0;
}
.user__avatar {
flex: 0 0 96px;
width: 96px;
height: 96px;
background-color: #e7e7e7;
}
.user__description {
flex: 1;
margin-left: 24px;
padding: 12px;
border: solid 1px #e7e7e7;
}

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

Давайте перейдемо до другого прикладу. На цей раз уявіть, що у нас є баннер, розташований у самій верхній частині розмітки. І ми хочемо розмістити всередині банера якийсь заголовок. На маленьких екранах висота банера дорівнює 180px, і вона буде змінюватися ще двічі, до значення 480px. І при всіх змінах висоти банера нам потрібно, щоб текст всередині був ідеально розташований по центру (як по горизонталі, так і по вертикалі). Ось стандартна розмітка:

Symmetrical Perfection

A beautiful sight, achieved with flexbox.

На цей раз ми задіяли також властивість justify-content, яке дозволить нам розподілити простір навколо елементів вздовж флекс-лінії. А ось CSS:

.banner {
display: flex;
align-items: center;
justify-content: space-around;
height: 180px;
background-color: #e7e7e7;
}
.banner__content {
text-align: center;
}
.banner__title,
.banner__sub {
margin: 0;
padding: 0;
line-height: 1.5;
}
@all media and ( min-width: 480px ) {
.banner {
height: 240px;
}
}
@all media and ( min-width: 768px ) {
.banner {
height: 360px;
}
}
@all media and ( min-width: 960px ) {
.banner {
height: 480px;
}
}

Неважливо, наскільки «високим» буде банер. Контент завжди буде ідеально отцентрирован по горизонталі і вертикалі. Ось в цьому і полягає міць флексбокса. Не забудьте подивитися демо-приклад.

Підтримка і вендорные префікси

Ви повинні знати ваш ринок і аудиторію… це ключовий момент. Флексбокс підтримується у всіх сучасних браузерах, включаючи IE10 і вище. Якщо ви займаєтеся створенням сучасних веб-додатків, то флексбокс — це потужний інструмент, і я дуже рекомендую його використовувати. Якщо ви створюєте або переробляєте веб-сайт, то перевірте статистику відвідуваності, щоб дізнатися вашу аудиторію. В даний час є ймовірність того, що близько 99% вашої аудиторії буде використовувати сучасні браузери.

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

Висновок

От і все! На цьому я закінчую цю статтю. Якщо ви хочете знайти реальний сайт, на якому використовується флексбокс, то можете навіть і не починати пошуки. На новому сайті callmenick.com флексбокс використовується практично скрізь! Спасибі, що прочитали статтю до кінця. Не забудьте, що ви можете подивитися демо-приклади, а також завантажити код за наведеними нижче посиланнями. Якщо у вас є якісь питання, зауваження чи побажання, залиште їх, будь ласка, в коментарях.