От автора: в CSS появились пользовательские свойства. Последнее время мы о них часто писали. Поддержка в браузерах хорошая, но ее нет и не будет в старых браузерах типа IE. Я так и вижу, насколько хорош будет «будущий CSS», если позволить препроцессорам портировать его на CSS, совместимый со старыми браузерами. Babel для CSS! Почему нет?!
И все же меня волнует тот факт, что это лишь некоторые примеры использования пользовательских свойств, которые можно прогнать через препроцессоры. Есть множество ситуаций, где то, что мы вытворяем с пользовательскими свойствами, нельзя прогнать через препроцессоры. Но если вы сделаете это, то попадете в очень странную ситуацию.
Если вы можете прогнать свойства через препроцессор и получить, что хотели, то, возможно, лучше использовать переменные самого препроцессора.
Препроцессоры не понимают структуру DOM
Дело не в том, что CSS применяется только к полностью построенному DOM. Не говоря уже о том, что любой CSS-файл лишь один из многих, влияющих на страницу.
Возможно, самый популярный препроцессор пользовательских свойств — postcss-custom-properties (идет вместе с cssnext). Только в нем можно объявлять переменные в :root:
1 2 3 4 5 6 |
:root { --backgroundColor: white; } .header { background-color: var(--backgroundColor); } |
Одно из самых полезных качеств пользовательских свойств CSS заключается в том, что их можно каскадировать. Пример взят из головы, но смысл вы поняли:
1 2 3 4 5 6 7 8 9 |
:root { --backgroundColor: white; } .header { background-color: var(--backgroundColor); } .header.is-about-page { --backgroundColor: yellow; } |
Препроцессор postcss-custom-properties обработает переменную в root, но не вариацию состояния, из-за чего получится довольно бесполезный CSS:
1 2 3 4 5 6 |
.header { background-color: white; } .header.is-about-page { --backgroundColor: yellow; } |
И разработчики знают об этом: «Трансформация не полная и не может быть полной (динамически каскадируемые переменные, в основе которых лежат пользовательские свойства, полагаются на дерево DOM). Сейчас целью является обеспечение надежного использования в будущем ограниченного подмножества (для селектора :root) функций нативных пользовательских CSS-свойств. Так как в контексте этого плагина мы не знаем DOM, то мы не можем добиться полностью безопасных выходных данных.»
Можете почитать по ссылке интересные беседы на эту тему. Есть еще один препроцессор пользовательских свойств — postcss-css-variables, и он старается пойти немного дальше. Например:
1 2 3 4 5 6 7 8 9 |
.header { background-color: var(--backgroundColor, white); } .header:hover { --backgroundColor: orange; } .header.is-about-page { --backgroundColor: yellow; } |
Дает нам:
1 2 3 4 5 6 |
.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 был очень крутой пример, в котором он менял направление градиента в медиа запросе, внося небольшие правки в пользовательское свойство (очень удобная функция).
1 2 3 4 5 6 7 8 9 10 11 12 |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
@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 на тех вещах, которые когда-то будут динамичными. Можно сразу обработать фолбеки, думая о кроссбраузерности, чтобы не прогонять что-то через препроцессор потом.
1 2 3 4 5 6 7 8 9 |
$brandColor: #f06d06; html { background: $brandColor; --base-font-size: 100%; font-size: 100%; font-size: var(--base-font-size); } |
Автор: Chris Coyier
Источник: //css-tricks.com/
Редакция: Команда webformyself.