Проблема з препроцессингом користувальницьких CSS-властивостей

18

Від автора: в CSS з’явилися власні властивості. Останнім часом ми про них часто писали. Підтримка в браузерах хороша, але її немає і не буде в старих браузерах типу IE. Я так і бачу, наскільки добре буде «майбутній CSS», якщо дозволити препроцессорам портувати його на CSS, сумісний зі старими браузерами. Babel для CSS! Чому ні?!

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

Якщо ви можете прогнати властивості через препроцесор і отримати, що хотіли, то, можливо, краще використовувати змінні самого препроцесора.

Препроцессоры не розуміють структуру DOM

Справа не в тому, що CSS застосовується тільки до повністю побудованому DOM. Не кажучи вже про те, що будь-CSS-файл лише один з багатьох, що впливають на сторінку.

Можливо, самий популярний препроцесор користувацьких властивостей — postcss-custom-properties (йде разом з cssnext). Тільки в ньому можна оголошувати змінні :root:

:root {
—backgroundColor: white;
}
.header {
background-color: var(—backgroundColor);
}

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

:root {
—backgroundColor: white;
}
.header {
background-color: var(—backgroundColor);
}
.header.is-about-page {
—backgroundColor: yellow;
}

Препроцесор postcss-custom-properties обробить змінну root, але не варіацію стану, із-за чого вийде досить марний CSS:

.header {
background-color: white;
}
.header.is-about-page {
—backgroundColor: yellow;
}

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

Можете почитати за посиланням цікаві бесіди на цю тему. Є ще один препроцесор користувацьких властивостей — postcss-css-variables, і він намагається піти трохи далі. Наприклад:

.header {
background-color: var(—backgroundColor, white);
}
.header:hover {
—backgroundColor: orange;
}
.header.is-about-page {
—backgroundColor: yellow;
}

Дає нам:

.header {
background-color: white;
}
.header:hover {
background-color: orange;
}

Даний препроцесор правильно обробляє hover, але не вміє працювати з селектором стану. Обидва плагіна погоджуються на думці, що не можна ідеально відтворити можливості користувальницьких CSS-властивостей у препроцессоре.

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

Ви не можете змінювати власні властивості через JavaScript

Крім каскадування, користувацькі властивості CSS можна міняти через JS з допомогою інший крутий функції. Щоб не отримувати DOM за допомогою JS для Х елементів, які потрібно змінити все окремо, можна просто змінити власну властивість.

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

Коли відключати препроцесор?

Можливо, ви думаєте про препроцессинге, як про щось тимчасове. У якийсь момент ви вимкніть його і скористаєтеся нативними корисними властивостями. Потрібно дещо врахувати:

нативна обробка точно така ж, як і в препроцессоре;

решті препроцессинг проходить нормально;

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

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

Деяким людям навіть подобається. Mike Street: «Я працюю в агентстві, де кросбраузерна підтримка стоїть на першому місці. Підтримувати потрібно навіть IE11 (на жаль). Хоча ми і не можемо використовувати CSS-змінні в продакшені, у них безліч переваг в розробці і постпроцесі до оригінальних властивостей.

У таск раннери gulp у нас є postcss-css-variables, який змінює все CSS-змінні стилях на зазначені значення. Майже як з SCSS-змінними (обробка проходить так само), але даний препроцесор дозволяє писати менше SCSS, а коли необхідно видаляє обробку і розгортає стилі з корисними властивостями.»

Думаю, потрібно трохи подумати. На сайті cssnext висить великий банер «Використовуйте синтаксис завтрашнього CSS вже сьогодні», і я боюся, що так вони намагаються під виглядом чогось простого продати дуже складний і тонкий інструмент.

Якщо ви використовуєте препроцесор для користувацьких властивостей, то ви можете також використовувати змінні самого препроцесора

Розумний вибір. У Sass, Less та Stylus є змінні, які відмінно працюють. У них навіть є якась область видимості, хоча і не така, як при реальному каскадування.

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

У Mike Street був дуже крутий приклад, в якому він змінював напрямок градієнта в медіа запиті, вносячи невеликі правки в користувальницьке властивість (дуже зручна функція).

div {
—direction: to bottom;
background: linear-gradient(
var(—direction),
rgba(0, 0, 0, 1) 0,
rgba(0, 0, 0, 0.1) 100%);
@media (max-width: 1000px) {
—direction: to right;
}
}

Опрацювати такий код спробує тільки postcss-css-variables (я так думаю). Код стислий, але подібний рівень абстракції можна отримати в SCSS.

@mixin specificGradient($direction) {
background: linear-gradient(
$direction,
rgba(0, 0, 0, 1) 0,
rgba(0, 0, 0, 0.1) 100%
);
}
div {
@include specificGradient(to bottom);
@media (max-width: 1000px) {
@include specificGradient(to right);
}
}

Використовуйте обидва варіанат/готуйте фолбеки вже зараз

Можна використовувати і препроцессоры, і настроювані властивості CSS. Дещо, наприклад $brandColor, можна навіть залишити у вигляді змінної препроцесора. У той же час можна використовувати користувальницькі властивості CSS на тих речах, які колись будуть динамічними. Можна відразу обробити фолбеки, думаючи про кросбраузерність, щоб не проганяти що через препроцесор потім.

$brandColor: #f06d06;
html {
background: $brandColor;
—base-font-size: 100%;
font-size: 100%;
font-size: var(—base-font-size);
}