Перехід на CSS Flexbox з допомогою методу виявлення

15

Від автора: для front-end розробників настав час відмовитися від використання властивості float в CSS і зануритися в новий захоплюючий світ flexbox. Підтримка Flexbox в CSS вже досить хороша, властивість flexbox підтримують всі сучасні браузери. Float застарілий метод стилізації; він підтримується в браузері IE, починаючи з 4 версії, і часто були потрібні різні обхідні шляхи для його повної працездатності (такі як clearfix і використання псевдокласу nth-child для блоку-обгортки колонок).

Вітаю вас, шановні читачі. У цій статті я розповім вам про цікавий методі виявлення, який можна використовувати при верстці Flexbox.

Кросбраузерна flexbox верстка можлива?

Головне завдання цієї статті – як створити кросбраузерність flexbox верстку, враховуючи фрагментацію flexbox. До кінця цій статті ви:

Зрозумієте, яка версія flexbox потрібна для чуйного сайту.

Будете використовувати flexbox допомогою методу виявлення (Cutting the mustard) і навчіться робити фікси для старих браузерів.

Відмовитеся від використання умовних коментарів для IE в більшості випадків.

На практиці створите базову сітку 2х2 з резервуванням для старих браузерів.

Коротка історія Flexbox

Модуль верстки з допомогою гнучких блоків (або flexbox) новий спосіб структурування коду верстки в CSS. За відносно короткий термін flexbox значно еволюціонував, і вийшло кілька версій. На момент написання статті flexbox був ще робочим стандарту W3C, але, як і інші стандарти, це не робить його «непривабливим» для розробки. Існує 3 типи стандарту, зазвичай згадують старий синтаксис, перехідний і новий.

Обмеження flexbox суворо задокументовані:

Старий синтаксис не підтримує flex-wrap.

Перехідною синтаксис підтримує flex-wrap тільки в IE10(включаючи мобільні браузери).

Новий синтаксис не повністю реалізований в Firefox(22-27) – відсутні властивості flex-wrap і flex-flow.

Обгортання flex-wrap важлива властивість у специфікації, воно необхідне для створення чуйною сітки. З цієї причини краще всього працювати з перехідним синтаксисом і версіями браузерів, які повністю підтримують новий синтаксис. У зв’язку з цим пропонуються наступні версії браузерів:

IE10 (перехідний синтаксис с-ms — префіксом)

IE11 і Edge (новий синтаксис)

Firefox28+ (новий синтаксис)

Chrome21-28 (новий синтаксис c -webkit — префіксом)

Chrome29+ (новий синтаксис)

Safari6.1+ (новий синтаксис c -webkit — префіксом)

iOS Safari7.0+ (новий синтаксис c -webkit — префіксом)

Так як достатня частка браузерів не підтримує flexbox необхідно робити резервування через float CSS. Але як це реалізувати в коді? Який із способів краще підходить для того, щоб розрізняти версії браузерів і використовувати float замість flexbox? Який підхід для підстраховки застосовувати до застарілими версіями Firefox, які підтримують новий синтаксис, але не підтримують обгортання? Уявляю – Cutting the mustard.

Виявлення особливостей (Cutting the Mustard)

Якщо ви ще не чули про це технічному терміні, «Cutting the mustard» був придуманий командою розробників BBC News. Значення терміна випливає з того, що сайт BBC зобов’язаний задовольняти інтерес величезної міжнародної аудиторії, і орієнтація на різні версії браузерів і специфікації пристроїв була громіздким рішенням.

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

Метод виявлення не новий. Вищезгадана стаття була опублікована в березні 2012 року. Поки цей метод тільки набирав популярність, дивно було бачити сайти, які все ще використовували спеціальні умовні класи для IE, винайдені Підлогою Иришем 2008.

Modernizr – тут є все про метод виявлення:

Застосування переваг нових крутих веб-технологій дуже весело до тих пір, поки вам не потрібно підтримувати застарілі браузери. Підтримує браузер дану функцію чи ні, Modernizr полегшує написання умов на JavaScript і CSS для обробки кожного випадку. Ідеально підходить для легкого створення прогресивних поліпшень.

Хоча зараз CSS має нативний метод виявлення, зараз його використання не досить поширене, щоб бути життєздатним. Далі в цій статті ми обговоримо, як відмовитися від умовних коментарів IE на користь методу виявлення на JavaScript.

Ідентифікуючі ознаки і браузери

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

Використання plain JavaScript (як у проекті BBC)

Використання бібліотеки Modernizr (Яка буде використана в цій статті)

Найефективніший метод – vanilla JavaScript. Він швидкий (не вимагає від користувача завантажувати додаткові бібліотеки) і не вимагає додаткової обробки. Цей метод далекий від досконалості, так як є відомі проблеми; однак, є способи подолання спільних проблем.

Визначення типу браузера стало нестерпним плутаниною, і в значній мірі вийшло з ужитку. Воно повинно бути замінено чимось набагато кращим методом визначення. …метод виявлення теж не цілком надійний – є моменти, де він не працює. Джеймс Едвардс

Бібліотека Modernizr для методу виявлення може бути не так ефективна (так як потрібно завантаження і обробки на стороні клієнта), але ручне виявлення підтримки властивості flex-wrap не просте завдання. Важливо також відзначити, що хоч Modernizr другої версії не визначає flex-wrap, зате третя версія це вміє! Ця функція названа Flex Line Wrapping.

Хоч в CSS і існує опція використання класів прикріплених до кореня документа Modernizr (наприклад: html.flexwrap), буде краще, якщо для кожного випадку буде створений окремий CSS файл. Це необхідно для зниження ваги завантажуваних файлів.

Розробники BBC News посилаються на два типи браузерів:

Хтось в команді почав називати їх «HTML4» і «HTML5» браузери. Так легше пояснити сенс людині, що не знає технічних особливостей.

Таке визначення браузерів було цілком справедливо, якщо врахувати, то які браузери були 2012; проте з появою нових функцій такий поділ стало не обов’язковим. Приміром, Firefox не повністю підтримується у всіх HTML5 браузерах.

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

Реалізація підходу

Почнемо з створення таких файлів:

index.html – головний HTML файл

stylesheets/modern.css – стилі для сучасних браузерів (медіа запити, flexbox з обгортанням)

stylesheets/legacy.css – стилі для старих браузерів (без медіа запитів, немає flexbox)

scripts/dependencies.js – виконує функцію виявлення.

Так виглядає наш index.html

Cutting the mustard

Cell 1
Cell 2
Cell 3
Cell 4

Помітили, що немає умовних коментарів IE? Просто чистий і дійсний HTML код. І навіть якщо в браузері вимкнено JavaScript, буде задіяний для страховки файл legacy.css не залежно від рівня його підтримки.

Також ви могли помітити, що теги JavaScript’а знаходяться в самому верху сторінки. Це зроблено для того, щоб Modernizr міг обробляти і вставляти стилі перед тим, як браузер отрисует сторінку при першому завантаженні. Це знижує можливість зміни кольорів і допомагає уникнути Flash Of Unstyled Content (FOUC). Але пам’ятайте, що більшість тегів скриптів будуть внизу сторінки. Файл legacy.css містить:

.container {
}
/* clearfix */
.container:after {
content: «»;
display: table;
clear: both;
}
.cell {
width: 50%;
float: left;
}
/* wrapping */
.cell:nth-child(2n+1) {
clear: left;
}
/* for visiblity */
.cell-1 { background-color: #000; color: #fff; }
.cell-2 { background-color: #666; color: #fff; }
.cell-3 { background-color: #ccc; color: #000; }
.cell-4 { background-color: #fff; color: #000; }

Реалізація включає clearfix хак і псевдоклас :nth-child для обгортання. Працює в більшості браузерів; однак IE8 потрібно Selectivizr або інше подібне рішення для правильної роботи селекторів. Далі наш файл modern.css:

.container {
/* Internet Explorer 10
*/
display: -ms-flexbox;
-ms-flex-wrap: wrap;
/* Chrome 21-28
* Safari 6.1+
* Opera 15-16
* iOS 7.0+
*/
display: -webkit-flex;
-webkit-flex-wrap: wrap;
/* Chrome 29+
* Firefox 28+
* Internet Explorer 11+
* Opera 12.1 & 17+
* Android 4.4+
*/
display: flex;
flex-wrap: wrap;
}
.cell {
-webkit-flex: 1 0 50%;
-ms-flex: 1 0 50%;
flex: 1 0 50%;
}
/* for visiblity */
.cell-1 { background-color: #000; color: #fff; }
.cell-2 { background-color: #666; color: #fff; }
.cell-3 { background-color: #ccc; color: #000; }
.cell-4 { background-color: #fff; color: #000; }

Не лякайтеся розміру файлу. Коментарі додають пару зайвих рядків, зате полегшують розуміння, для чого потрібна кожна секція. Наступним буде файл dependencies.js. Як було вже сказано, нам необхідно згенерувати третю версію Modernizr, яка визначає підтримку flex-wrap. Код нижче потрібно додати в початок скрипта.

/* Include Modernizr v3 with ‘Flex line wrapping’ here */
(function() {
var isModern = Modernizr.flexwrap;
var link = document.createElement(‘link’);
link.rel = ‘stylesheet’;
link.type = ‘text/css’;
link.href = ‘stylesheets/’ + (isModern ? ‘modern’ : ‘legacy’) + ‘.css’;
document.getElementsByTagName(‘head’)[0].appendChild(link);
})();

При бажанні ви можете збільшити вимоги для сучасних браузерів, додавши до isModern Boolean. Наприклад:

var isModern = Modernizr.flexwrap && ‘querySelector’ in document;

Рішення з допомогою Sass

Ви можете використовувати Saas щоб зробити абстрактним метод реалізації flexbox. Це зменшить розмір вихідного CSS файлу і полегшує обслуговування:

%flexbox {
display: -ms-flexbox;
-ms-flex-wrap: wrap;
display: -webkit-flex;
-webkit-flex-wrap: wrap;
display: flex;
flex-wrap: wrap;
}
.container1 {
@extend %flexbox;
}
.container2 {
@extend %flexbox;
}

Прогресивне поліпшення і тестування в браузерах

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

Наприклад, за замовчуванням flexbox розтягує всі осередки в низці до однієї висоти. Тому якщо одна клітина довжиною 3 і сусідня рядок довжиною 10, то фон розтягнеться для обох клітин до 10. Резервування на float CSS так не може, і тому комірки будуть мати різну висоту.

Тестування верстки в безлічі браузерів все ще потрібно, але важливо не забувати, що прирівнювання isModern до false dependencies.js допоможе протестувати застарілі рішення в будь-якому браузері.

var isModern = false; // Modernizr.flexwrap;

Висновок

У цій статті я показав основи використання функції виявлення для роботи з двома різними файлами стилів і однієї версткою. Це надзвичайно ефективний спосіб почати позбуватися від властивості float CSS і знизити залежність від умовних коментарів IE.

Хоча, був зроблений великий акцент на визначенні підтримки flexbox, важливо відзначити, що як нова функція, розроблена для браузерів, метод виявлення може бути адаптований і розвинений в відповідності з майбутніми вимогами.

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

Так що тепер у вас є основи. І чому б не використовувати flexbox у вашому наступному проекті?