Оригинальный адрес: woohoo.smashing magazine.com/2018/05/CSS…
Адрес перевода: GitHub.com/read-share/have-he…
Переводчик: Бобо
Корректор: ziven27,маленький человек
Об автореМайк – независимый веб-разработчик из Австралии, который работал с несколькими крупными сайтами и небольшими сообществами в Австралии... Подробнее о Майкле...
Пользовательские свойства CSS (также известные как «переменные CSS»), которые в настоящее время поддерживаются во всех современных браузерах, использовались разработчиками в проектах, но они не совпадают с переменными в препроцессорах, хотя я видел много примеров, но я так и не понял, в чем заключаются их реальные преимущества.
Пользовательские свойства могут изменить то, как мы пишем и организуем CSS, и в некоторой степени то, как вызываются компоненты JavaScript и пользовательского интерфейса. Меня не волнует синтаксис и то, как они работают (для этого я предлагаю вам прочитать "Сейчас самое время начать использовать пользовательские свойствав этой статье).В то же время я хотел глубже изучить, как получить максимальную отдачу от пользовательских свойств CSS.
Чем пользовательские атрибуты похожи на переменные в препроцессоре?
Пользовательские свойства немного похожи на переменные в препроцессоре, но все же есть большая разница. Самое важное и очевидное отличие заключается в синтаксисе.
В SCSS мы используем символ $ для определения переменных:
$smashing-red: #d33a2c;
В Less мы используем символ @:
@smashing-red: #d33a2c;
Пользовательские свойства следуют аналогичному соглашению и используют префикс --:
:root { --smashing-red: #d33a2c; }
.smashing-text {
color: var(--smashing-red);
}
Самая большая разница между пользовательскими свойствами и переменными в препроцессоре заключается в правилах синтаксиса для «пар ключ-значение». Пользовательские свойства используют функцию var() для получения значений.
Еще одно очевидное отличие — название. Они называются «настраиваемые свойства», потому что они являются чистыми свойствами CSS. В препроцессоре вы можете объявлять и использовать переменные где угодно, в том числе вне блоков объявления, в медиа-запросах и даже в селекторах, например:
$breakpoint: 800px;
$smashing-red: #d33a2c;
$smashing-things: ".smashing-text, .cats";
@media screen and (min-width: $breakpoint) {
#{$smashing-things} {
color: $smashing-red;
}
}
С пользовательскими свойствами большинство приведенных выше примеров недействительны.
Пользовательские свойства используются так же, как и обычные свойства CSS. Лучше рассматривать их как динамические свойства, чем переменные. Это означает, что их можно использовать только в блоках объявлений, другими словами, пользовательские свойства и селекторы строго связаны. Это может быть селектор :root или любой другой допустимый селектор.
:root { --smashing-red: #d33a2c; }
@media screen and (min-width: 800px) {
.smashing-text, .cats {
--margin-left: 1em;
}
}
Вы можете получить значение объявления переменной в любом месте объявления свойства, что означает, что их можно использовать как отдельное значение, как часть сокращенного оператора или даже в функции calc().
.smashing-text, .cats {
color: var(--smashing-red);
margin: 0 var(--margin-horizontal);
padding: calc(var(--margin-horizontal) / 2)
}
Однако они не могут быть использованы в средствах массовой информации или селекторов, в том числе: Nth-Child ().
Вероятно, существует гораздо больше информации о том, как работает синтаксис и пользовательские свойства, например, как используются резервные значения и как мы можем назначать переменные другим переменным, но основ, описанных в этой статье, должно быть достаточно для понимания концепций. Для получения более подробной информации о том, как работают настраиваемые свойства, вы можете прочитать "Время начать использовать настраиваемые свойства"Эта статья.
Динамические и статические переменные
Помимо различий в стилях, самая большая разница между переменными в препроцессоре и переменными в пользовательских свойствах заключается в области действия. Мы можем разделить переменные на статические переменные и динамические переменные в соответствии с их областью действия. Переменные в препроцессоре являются статическими, а пользовательские свойства — динамическими.
В CSS статика означает, что вы можете обновить значение переменной во время компиляции, но это не может изменить ее предыдущее значение.
$background: blue;
.blue {
background: $background;
}
$background: red;
.red {
background: $background;
}
оказаться:
.blue {
background: blue;
}
.red {
background: red;
}
После компиляции в CSS эта переменная исчезает. Это означает, что нам не нужно заботиться о HTML, браузере или другом вводе при чтении файла .scss и его выводе, чего нельзя сказать о настраиваемых свойствах. Препроцессор имеет своего рода «блочную область», в которой переменные могут быть временно изменены в селекторах, функциях или примесях. Это изменяет значение переменной внутри блока, но оно остается статическим. Речь идет о блоках, а не о селекторах. В приведенном ниже примере переменная $background изменяется внутри класса .example. Даже если мы используем тот же селектор, он возвращается к исходному значению вне области действия блока.
$background: red;
.example {
$background: blue;
background: $background;
}
.example {
background: $background;
}
После компиляции:
.example {
background: blue;
}
.example {
background: red;
}
Пользовательские свойства отличаются от препроцессоров. Там, где задействованы настраиваемые свойства, динамическая область видимости означает, что они подлежат наследованию и каскадированию. Свойства привязаны к селекторам, и если значение изменяется, они влияют на все соответствующие элементы DOM, как и любое другое свойство CSS.
Звучит здорово, потому что вы можете изменить значение пользовательских свойств в медиа-запросах, используя селекторы псевдоклассов, похожие на наведение, или даже JavaScript.
a {
--link-color: black;
}
a:hover,
a:focus {
--link-color: tomato;
}
@media screen and (min-width: 600px) {
a {
--link-color: blue;
}
}
a {
color: var(--link-color);
}
Нам не нужно изменять пользовательское свойство там, где оно используется, мы можем изменить его значение с помощью CSS. Это означает, что одно и то же пользовательское свойство может иметь разные значения в разных местах или контекстах.
Глобальные и локальные переменные
Помимо статических и динамических переменных, переменные также могут быть глобальными или локальными. Если вы много пишете на JavaScript, вы, вероятно, знаете это лучше. Переменные могут либо действовать в глобальной среде приложения, либо ограничивать свою область действия определенной функцией или блоком кода.
То же самое касается CSS. Существуют глобальные переменные и локальные переменные. Фирменные цвета, вертикальный интервал, типографика — вы можете называть их глобально на стороне приложения и на веб-странице. Конечно, есть и некоторые локальные вещи, например, компонент кнопки может иметь размер. Вы не хотите, чтобы размер этих кнопок соответствовал всем элементам ввода или каждому элементу на странице.
Это вариант использования, с которым мы знакомы в CSS. Мы разработали системы дизайна, соглашения об именах и библиотеки JavaScript, которые разделяют локальные и глобальные компоненты. Пользовательские атрибуты позволяют по-новому взглянуть на проблему такого типа.
Обычно объем пользовательских свойств CSS ограничен указанными селекторами. Это немного похоже на локальную переменную. Однако пользовательские свойства наследуются, поэтому в большинстве случаев они ведут себя скорее как глобальные переменные, особенно при применении к селектору :root. Это означает, что нам нужно подумать о том, как их использовать.
Во многих примерах показано применение пользовательских атрибутов к элементу :root, что имеет смысл для демонстрации, но может загрязнить глобальную область видимости и вызвать неожиданные проблемы с наследованием. К счастью, мы усвоили урок.
Глобальные переменные, как правило, статичны.
Могут быть некоторые исключения, но в целом большинство глобальных переменных в CSS также статичны.
Такие переменные, как фирменные цвета, шрифты и интервалы, не сильно отличаются от компонента к компоненту. Когда они меняются, часто это глобальный ребрендинг или другие большие изменения, которые редко случаются со зрелым продуктом. Для этих переменных они по-прежнему имеют смысл, они используются во многих местах, а переменные помогают поддерживать согласованность. Но делать их динамическими переменными не имеет смысла. Значения этих переменных не изменяются никаким динамическим образом.
Поэтому я настоятельно рекомендую использовать препроцессор для глобальных (статических) переменных. Это не только гарантирует, что они всегда статичны, но и делает их более интуитивно понятными в коде. Это может упростить чтение и поддержку CSS.
Локальные статические переменные также используются как можно реже.
Вы можете подумать, что глобальные переменные имеют тенденцию быть статичными, поэтому, возможно, наоборот, все локальные переменные должны быть динамическими, но на самом деле это намного удобнее для разработки, чем статические глобальные переменные. Локальные статические переменные во многих случаях являются динамическими, потому что я использую переменные препроцессора в файлах компонентов, в основном для удобства разработки.
Мой SCSS может выглядеть так:
$button-sml: 1em;
$button-med: 1.5em;
$button-lrg: 2em;
.btn {
// Visual styles
}
.btn-sml {
font-size: $button-sml;
}
.btn-med {
font-size: $button-med;
}
.btn-lrg {
font-size: $button-lrg;
}
Очевидно, что этот пример имел бы больше смысла, если бы я использовал переменную несколько раз или вычислял значение поля или отступа из переменной. Тем не менее, возможность быстрого прототипирования различных размеров может быть веской причиной.
Поскольку большинство статических переменных являются глобальными, мне нравится различать статические переменные, которые используются только внутри компонента. Для этого вы можете добавить к этим переменным префикс имени компонента или использовать другой префикс, например, имя переменной c или имя переменной l компонента. Вы можете использовать любой префикс или глобальные переменные. Независимо от того, что вы выберете, различие полезно, особенно при преобразовании существующего кода для использования пользовательских свойств.
Когда использовать настраиваемые свойства
Если вы можете использовать статические переменные внутри компонента, когда вы должны использовать пользовательские свойства?Преобразование существующих переменных препроцессора в пользовательские свойства обычно не имеет смысла. Ведь назначение пользовательских свойств совсем другое. Пользовательские свойства имеют смысл, когда у нас есть свойства CSS, особенно в DOM (особенно динамические условия), такие как: fouces, hover, медиа-запросы или JavaScript.
Я предполагаю, что мы всегда будем использовать некоторую форму статических переменных, хотя в будущем нам может понадобиться меньше статических переменных, поскольку пользовательские свойства предоставляют новые способы организации логики и кода. До этого я думал, что в большинстве случаев мы могли бы использовать комбинацию переменных препроцессора и пользовательских свойств.
Мы можем назначать статические переменные для пользовательских свойств. Независимо от того, являются ли они глобальными или локальными, во многих случаях имеет смысл преобразовывать статические переменные в локальные динамические пользовательские свойства.
Примечание: вы знаете
$var
является допустимым значением для настраиваемого свойства?Последние версии Sass распознают это, поэтому нам нужно вставить переменные, назначенные настраиваемым свойствам, например:#{$var}
. Это говорит Sass, что вы хотите вывести значение переменной, а не значение в таблице стилей.$var
. Это работает только в таких случаях, как настраиваемые свойства, где имена переменных также могут быть действительными CSS.
Если мы возьмем приведенный выше пример кнопки и решим, что все кнопки должны использовать небольшие изменения на мобильных устройствах, независимо от класса, примененного в HTML, ситуация будет более динамичной. Для этого мы должны использовать пользовательские свойства.
$button-sml: 1em;
$button-med: 1.5em;
$button-lrg: 2em;
.btn {
--button-size: #{$button-sml};
}
@media screen and (min-width: 600px) {
.btn-med {
--button-size: #{$button-med};
}
.btn-lrg {
--button-size: #{$button-lrg};
}
}
.btn {
font-size: var(--button-size);
}
Здесь я создал пользовательское свойство: --button-size. Этот настраиваемый атрибут изначально привязан ко всем элементам кнопки с использованием класса btn. Затем я изменил размер кнопки для классов btn-med и btn-lrg, чтобы он был выше 600 пикселей. Наконец, я применяю этот настраиваемый атрибут ко всем элементам кнопок в одной позиции.
Не будь слишком умным
Динамический характер пользовательских свойств позволяет нам создавать умные и сложные компоненты.
С введением препроцессоров многие из нас могут создавать библиотеки с умными абстракциями, используя примеси и пользовательские функции. В ограниченных случаях подобные примеры все еще полезны, но в основном я использую меньше функциональности, чем дольше я использую препроцессор. Прямо сейчас сценарии, в которых я использую препроцессор, в основном относятся только к части статических переменных.
То же самое относится и к пользовательским свойствам, и я с нетерпением жду более умных примеров. Но читаемый и поддерживаемый код всегда лучше в долгосрочной перспективе (по крайней мере, в проектах).
Недавно я прочитал отличную статью на эту тему на Free Code Camp Medium. Она была написана Биллом Суруром и называется «Не делайте это во время выполнения, делайте это во время разработки’. Вместо того, чтобы объяснять свою точку зрения, я рекомендую вам сначала прочитать эту статью.
Основное различие между переменными предварительной обработки и пользовательскими свойствами заключается в том, что пользовательские свойства работают во время выполнения. Это означает, что пользовательские свойства приемлемы с точки зрения сложности, поскольку у препроцессора нет такого хорошего способа пользовательских свойств.
Пример, который я недавно использовал для иллюстрации:
:root {
--font-scale: 1.2;
--font-size-1: calc(var(--font-scale) * var(--font-size-2));
--font-size-2: calc(var(--font-scale) * var(--font-size-3));
--font-size-3: calc(var(--font-scale) * var(--font-size-4));
--font-size-4: 1rem;
}
Это дает пропорциональную составляющую. Пропорциональный компонент представляет собой ряд чисел, связанных с соотношением. Они часто используются в веб-дизайне и разработке для установки размера шрифта или интервала.
В этом примере каждое пользовательское свойство определяется с помощью функции calc() путем взятия значения предыдущего пользовательского свойства и умножения его на коэффициент. Делая это, мы можем получить следующее число.
Это означает, что соотношения рассчитываются во время выполнения, и вы можете изменить их, просто обновив значение свойства --font-size. Например:
@media screen and (min-width: 800px) {
:root {
--font-scale: 1.33;
}
}
Если вы хотите изменить масштаб, это умно, лаконично и намного быстрее, чем заново вычислять все значения. Это также то, что я не делаю во время разработки.
Хотя приведенный выше пример полезен для прототипирования, в процессе разработки я предпочитаю видеть что-то вроде этого:
:root {
--font-size-1: 1.728rem;
--font-size-2: 1.44rem;
--font-size-3: 1.2em;
--font-size-4: 1em;
}
@media screen and (min-width: 800px) {
:root {
--font-size-1: 2.369rem;
--font-size-2: 1.777rem;
--font-size-3: 1.333rem;
--font-size-4: 1rem;
}
}
Как и в примере из статьи Билла, мне было полезно посмотреть, что означают фактические значения. Мы читаем код намного чаще, чем пишем его, и глобальные параметры, такие как шрифты, редко меняются в разных проектах.
Приведенный выше пример не идеален. Это нарушает предыдущее правило, согласно которому глобальные переменные должны быть статическими. Я бы предпочел использовать переменные препроцессора и преобразовывать их в локальные динамические пользовательские свойства, используя пример, продемонстрированный ранее.
Также важно избегать ситуаций, когда вы используете одно пользовательское свойство для другого. Это происходит, когда мы называем свойства подобным образом.
Изменить значения свойств вместо переменных
Это одно из наиболее важных указаний по использованию настраиваемых свойств.
Как правило, изменение пользовательских свойств с какой-то одной целью не рекомендуется. Хотя это легко реализовать, потому что это именно то, что должен делать препроцессор, это не имеет особого смысла для пользовательских атрибутов.
В этом примере для примера компонента мы создали два настраиваемых свойства для использования. Измените пользовательское свойство --font-size-small на --font-size-large в соответствии с размером экрана.
:root {
--font-size-small: 1.2em;
--font-size-large: 2em;
}
.example {
font-size: var(--font-size-small);
}
@media screen and (min-width: 800px) {
.example {
font-size: var(--font-size-large);
}
}
Лучший способ — определить только один настраиваемый атрибут в этом компоненте, а затем изменить значение этого атрибута с помощью медиа-запросов или других селекторов.
.example {
--example-font-size: 1.2em;
}
@media screen and (min-width: 800px) {
.example {
--example-font-size: 2em;
}
}
Наконец, просто получите нужное значение свойства, вызвав это пользовательское свойство.
.example {
font-size: var(--example-font-size);
}
В этом и предыдущем примерах мы просто используем медиа-запросы для изменения значения пользовательского свойства. Он также объявляет это пользовательское свойство через var() только в одном месте, а затем значение CSS автоматически обновляется через это пользовательское свойство.
Мы намеренно отделяем объявления значений от объявлений свойств по ряду причин, наиболее очевидным примером которых является адаптивный дизайн.
Создавайте адаптивные макеты с настраиваемыми свойствами
Самая большая трудность адаптивного макета заключается в том, что он настолько зависит от медиа-запросов, что независимо от того, насколько тщательно вы управляете своим CSS, стили, связанные с компонентами, могут стать фрагментированными.
Трудно сказать, какие свойства CSS изменятся. Пользовательские свойства CSS могут помочь нам справиться с этой логической взаимосвязью, связанной с адаптивным дизайном, тем самым уменьшив сложность использования медиа-запросов.
Если он меняется, это просто переменная
Изменение свойств в медиа-запросах само по себе является динамическим, а пользовательские свойства как раз восполняют отсутствие динамических характеристик свойств CSS. Это означает, что если вы хотите изменить свойства CSS с помощью медиа-запросов, пользовательские свойства — хороший выбор.
Затем вы можете переместить правила медиа-запроса, состояние наведения или любой динамический селектор, определяющий способ изменения значения свойства, в верхнюю часть документа.
Разделение логики и дизайна
Если вы все делаете правильно, разделение логики и дизайна означает, что медиа-запросы используются только для изменения значения пользовательских свойств. Это означает, что вся логика, связанная с адаптивным дизайном, должна быть размещена в верхней части документа, и везде, где мы видим оператор var(), очевидно, что это свойство изменится. С традиционным CSS мы бы не смогли это обнаружить.
Большинство из нас очень хорошо читают и понимают CSS, и нам нужно подумать о том, какие свойства изменяются в разных состояниях. С меня хватит этого пути. Теперь пользовательские свойства помогают нам связать логику и реализацию, поэтому нам не нужно отслеживать эти изменения в мозгу, что действительно полезно в проектах!
складная логика
Идея объявления переменных вверху документа или функции — очень старый способ. Также рекомендуется для большинства языков, а теперь мы можем сделать это и в CSS. Написание CSS таким образом позволяет легко различать верхний и следующий код только с визуальной точки зрения. Я могу легко найти их, когда захочу их использовать. И это концепция «складывающейся логики», которую я подчеркиваю. Выше этой складки находятся все переменные препроцессора и пользовательские свойства. Это включает в себя все возможные варианты параметров и пользовательских свойств. Таким образом, мы можем легко узнать, какие изменения произошли с пользовательскими свойствами.
Код CSS после этой складки тоже очень читабелен, что ничем не отличается от написания медиазапросов и прочего необходимого кода.
Давайте рассмотрим очень простой пример системы сеток для макета Flexbox с шестью столбцами:
.row {
--row-display: block;
}
@media screen and (min-width: 600px) {
.row {
--row-display: flex;
}
}
Начальное значение этого пользовательского свойства -row-display равно block. Это значение будет сброшено на flex, когда размер экрана превысит 600 пикселей.
Код под свернутой областью может выглядеть так:
.row {
display: var(--row-display);
flex-direction: row;
flex-wrap: nowrap;
}
.col-1, .col-2, .col-3,
.col-4, .col-5, .col-6 {
flex-grow: 0;
flex-shrink: 0;
}
.col-1 { flex-basis: 16.66%; }
.col-2 { flex-basis: 33.33%; }
.col-3 { flex-basis: 50%; }
.col-4 { flex-basis: 66.66%; }
.col-5 { flex-basis: 83.33%; }
.col-6 { flex-basis: 100%; }
Мы можем интуитивно понять, что --row-display является переменной. И его значение теперь должно быть блочным, а не гибким.
Это простой пример, но значения flex-grow, flex-shrink и flex-basis также необходимо преобразовать в пользовательские свойства, если мы хотим расширить столбец, заполняющий оставшееся пространство. Вы можете попробовать написать его, или нажмите здесь, чтобы посмотретьболее подробный пример.
Создание пользовательских свойств на основе тем
Я не рекомендую использовать настраиваемые свойства для создания глобальных динамических переменных, а также не рекомендую присоединять настраиваемые свойства к области селектора :root. Но из каждого правила есть исключение, и для пользовательских свойств, в случае создания темы, это исключение.
Ограниченное использование глобальных настраиваемых свойств может упростить создание темы.
Тематика обычно означает предоставление пользователю возможности настраивать пользовательский интерфейс определенным образом. Это может быть похоже на изменение цветов в файле конфигурации. Проще говоря, вы выбрали цвет для своих заметок в приложении Google Keep.
Темы часто имеют отдельные таблицы стилей для переопределения предыдущих стилей на основе выбора пользователя или полностью отдельные файлы таблиц стилей для разных стилей. Оба метода сложны в реализации и влияют на производительность.
Используйте все заглавные буквы для представления глобальных динамических свойств.
Пользовательские свойства чувствительны к регистру, а пользовательские свойства рекомендуется указывать локально. Если вам необходимо использовать глобальные динамические свойства, рекомендуется использовать все заглавные буквы.
:root {
--THEME-COLOR: var(--user-theme-color, #d33a2c);
}
Переменные с заглавными буквами часто используются для представления глобальных констант. Для нас, как только мы видим переменную во всех заглавных буквах, это означает, что свойство является глобальным и мы не должны изменять его локально.
Избегайте прямой установки глобальных динамических свойств
Пользовательские свойства могут принимать альтернативное значение. Мы должны избегать прямого переопределения значения глобальных пользовательских свойств и пытаться отделить их от других значений. Для этого мы можем использовать альтернативные значения.
В предыдущем примере мы установили для параметра --THEME-COLOR значение --user-theme-color. Если --user-theme-color не задан, будет использоваться альтернативное значение #d33a2c. Таким образом, нам не нужно предоставлять альтернативное значение каждый раз, когда используется --THEME-COLOR.
В приведенном ниже примере вы, вероятно, хотите, чтобы фон был зеленым. Но значение --user-theme-color в области :root не установлено, поэтому окончательное значение --THEME-COOR не изменится.
:root {
--THEME-COLOR: var(--user-theme-color, #d33a2c);
}
body {
--user-theme-color: green;
background: var(--THEME-COLOR);
}
Косвенная установка глобальных динамических свойств предотвращает их локальное переопределение и гарантирует, что пользовательские настройки всегда наследуются от корневого элемента. Это соглашение предотвращает случайное наследование параметров темы.
Если мы хотим показать какие-то определенные свойства, мы можем заменить селектор :root на селектор *:
* {
--THEME-COLOR: var(--user-theme-color, #d33a2c);
}
body {
--user-theme-color: green;
background: var(--THEME-COLOR);
}
Теперь значение --THEME-COLOR пересчитывается в каждом элементе, поэтому можно использовать локальную переменную --user-theme-color. Другими словами, цвет фона в этом примере — зеленый.
ты сможешьКонтроль цветов с пользовательскими свойствами” для более подробных примеров.
Обновление пользовательских свойств с помощью JavaScript
Если вы хотите установить пользовательские свойства с помощью JavaScript, вот довольно простой API:
const elm = document.documentElement;
elm.style.setProperty('--USER-THEME-COLOR', 'tomato');
Здесь я установил значение элемента --USER-THEME-COLOR, другими словами, :root будет унаследован всеми элементами.
Это не новый API, это просто метод JavaScript для обновления стилей элементов. Это встроенные стили, поэтому они имеют больший вес, чем обычный CSS.
Это упрощает локальную настройку:
.note {
--note-color: #eaeaea;
}
.note {
background: var(--note-color);
}
Здесь я установил значение по умолчанию --note-color и применил его к компоненту .note. Даже в этом простом примере я отделяю объявления переменных от объявлений свойств.
const elm = document.querySelector('#note-uid');
elm.style.setProperty('--note-color', 'yellow');
Затем я нацеливаюсь на экземпляр элемента .note и просто меняю значение пользовательского атрибута --note-color для этого экземпляра. Это будет иметь более высокий вес, чем значение по умолчанию.
Вы можете смотретьПример использования Reactчтобы узнать, как это работает. Эти пользовательские настройки можно сохранить в локальном хранилище или, в более крупных приложениях, в базе данных.
Управляйте цветами с помощью настраиваемых свойств
В дополнение к шестнадцатеричным значениям и именованным цветам в CSS есть цветовые методы, такие как rgb() и hsl(), которые вы можете использовать. Они позволяют нам устанавливать определенные свойства цвета, такие как оттенок или яркость для компонента. Пользовательские свойства можно использовать в сочетании с этими методами.
:root {
--hue: 25;
}
body {
background: hsl(var(--hue), 80%, 50%);
}
Это полезно, и препроцессор предоставляет более продвинутые методы цвета, которые мы можем использовать для осветления, затемнения или обесцвечивания цветов:
darken($base-color, 10%);
lighten($base-color, 10%);
desaturate($base-color, 20%);
Было бы лучше, если бы браузер сам предоставлял эти методы. "они идут», но до тех пор, пока CSS изначально не поддерживает эти возможности, пользовательские свойства — это то, что нужно, чтобы заполнить пустоту.
Мы видели, что пользовательские свойства можно использовать не только в цветовых методах, таких как rgb(), hsl(), но и в calc(). Это означает, что мы можем преобразовать число в процентное значение, умножив его, например, calc(50 * 1%) = 50%.
:root {
--lightness: 50;
}
body {
background: hsl(25, 80%, calc(var(--lightness) * 1%));
}
Причина, по которой мы сохраняем значение яркости в виде целого числа, заключается в том, что мы можем использовать метод calc для его преобразования перед преобразованием в проценты. Например, если я хочу затемнить цвет на 20%, я могу умножить его значение яркости на 0,8, чтобы добиться этого. Настраиваемыми атрибутами метод расчета яркости ограничен локальной областью видимости, что может сделать наш код более читабельным:
:root {
--lightness: 50;
}
body {
--lightness: calc(var(--lightness * 0.8));
background: hsl(25, 80%, calc(var(--lightness) * 1%));
}
Мы можем даже абстрагироваться от дополнительных методов вычислений и создать что-то вроде "Функция расширения цвета на основе пользовательских свойств CSSЭтот пример может быть относительно сложным для реальной ситуации с большинством тем, но он полностью демонстрирует мощь динамических пользовательских свойств.
Упростите тему
Одним из преимуществ использования настраиваемых свойств является то, что это значительно упрощает создание тем. Приложению не нужно знать, как используется настраиваемый атрибут. Вместо этого мы устанавливаем значения пользовательских свойств через JavaScript или код на стороне сервера, которые, в свою очередь, контролируются непосредственно таблицей стилей.
Это означает, что мы дополнительно отделяем логику от дизайна. Если у вас есть профессиональная команда дизайнеров, дизайнеры могут решать, как применять настраиваемые свойства, обновляя таблицу стилей, не изменяя ни одной строки JavaScript или внутреннего кода.
Пользовательские свойства переносят сложность темы в CSS, и эта сложность может негативно повлиять на удобство сопровождения CSS, поэтому, возможно, сделайте тему простой.
Время использовать настраиваемые атрибуты
Даже если вашему проекту по-прежнему требуется поддержка IE10 и IE11, вы все равно можете использовать настраиваемые свойства. Большинство примеров в этой статье посвящено тому, как писать и создавать CSS. Однако эти преимущества значительны с точки зрения удобства сопровождения, и большинство примеров в этой статье просто сокращают количество вещей, которые в противном случае потребовали бы более сложного кода.
Я использую файл с именемpostcss-css-variablesИнструмент преобразует большинство методов пользовательских свойств в статические методы с той же функциональностью. Другие подобные инструменты игнорируют медиа-запросы или пользовательские атрибуты в сложных селекторах и обрабатывают их как переменные предварительной обработки.
Чего эти инструменты не могут сделать, так это имитировать поведение пользовательских свойств в реальном времени. А это означает потерю динамических функций, о которых мы упоминали ранее при создании тем, и изменение свойств с помощью JavaScript. Это также допустимо во многих случаях. В конце концов, в зависимости от ситуации, пользовательский интерфейс также является способом прогрессивного улучшения, а тема по умолчанию вполне приемлема для старых браузеров.
Загрузите правильную таблицу стилей
Есть много людей, которые используют postCSS. Я использую процесс Gulp, чтобы различать таблицы стилей старых и новых браузеров. Задача Gulp, которую я создал, выглядит следующим образом:
import gulp from "gulp";
import sass from "gulp-sass";
import postcss from "gulp-postcss";
import rename from "gulp-rename";
import cssvariables from "postcss-css-variables";
import autoprefixer from "autoprefixer";
import cssnano from "cssnano";
gulp.task("css-no-vars", () =>
gulp
.src("./src/css/*.scss")
.pipe(sass().on("error", sass.logError))
.pipe(postcss([cssvariables(), cssnano()]))
.pipe(rename({ extname: ".no-vars.css" }))
.pipe(gulp.dest("./dist/css"))
);
gulp.task("css", () =>
gulp
.src("./src/css/*.scss")
.pipe(sass().on("error", sass.logError))
.pipe(postcss([cssnano()]))
.pipe(rename({ extname: ".css" }))
.pipe(gulp.dest("./dist/css"))
);
В результате будут выведены два файла CSS: один с пользовательскими свойствами (styles.css) и один для старых браузеров (styles.no-vars.css). Я хотел бы использовать файл styles.no-vars.css для браузеров IE10 и IE11 и обычный файл CSS для других браузеров.
Как правило, я выступаю за использование функциональных запросов, но "IE11 не поддерживает запросы функций", но мы уже много используем пользовательские свойства, и в этом случае имеет смысл предоставить для них другую таблицу стилей.
Избежать мерцания нестилизованного содержимого, предоставив другую таблицу стилей, непросто. Если вам не нужны динамические функции в настраиваемых свойствах, рассмотрите возможность использования файла styles.no-vars.css для всех браузеров, а настраиваемые свойства — только в качестве инструмента разработки.
Если вы хотите воспользоваться всеми преимуществами динамического характера пользовательских свойств, я рекомендую использовать "Ключевые приемы CSS". Основываясь на этих методах, основная таблица стилей загружается асинхронно, в то время как критически важный CSS встраивается. Заголовок вашей страницы может выглядеть так:
<head>
<style> /* inlined critical CSS */ </style>
<script> loadCSS('non-critical.css'); </script>
</head>
Мы можем расширить этот метод, чтобы решить, следует ли загружать styles.css или styles.no-vars.css в зависимости от того, поддерживает ли браузер пользовательские свойства. Мы можем сделать это так:
if ( window.CSS && CSS.supports('color', 'var(--test)') ) {
loadCSS('styles.css');
} else {
loadCSS('styles.no-vars.css');
}
В заключение
Если вы хотите более эффективно управлять CSS, испытываете трудности с использованием адаптивных функций, хотите добиться эффекта, похожего на тему на стороне клиента, или просто хотите поэкспериментировать с настраиваемыми свойствами, эта статья должна помочь вам ответить на эти вопросы. Это не только объясняет разницу между динамическими и статическими переменными в CSS, но и несколько других правил:
- Отделение логики от дизайна;
- Если свойства CSS необходимо изменить, рассмотрите возможность использования настраиваемых свойств;
- Измените только значение настраиваемого свойства, но не само настраиваемое свойство;
- Глобальные переменные обычно статические.
Если вы понимаете приведенные выше правила, вы обнаружите, что использование настраиваемых свойств намного проще, чем вы думаете, и может даже изменить способ работы с CSS.
дальнейшее чтение
"Время использовать настраиваемые атрибуты», синтаксис и свойства пользовательских свойств, представленных Сергом Господарцем.
"Отвратительные практичные пользовательские свойства CSS, с более полезной информацией по этому вопросу от Гарри Робертса.
"Коллекция пользовательских свойств", обширные и разнообразные примеры Майка Ритмюллера на CodePen.