Сделайте свой CSS динамическим с помощью пользовательских свойств CSS
Опубликовано: 2022-03-11Если вы какое-то время писали CSS, вы, должно быть, в какой-то момент почувствовали потребность в переменных. Пользовательские свойства CSS чем-то напоминают собственную реализацию переменных CSS. Однако при правильном использовании они могут быть гораздо больше, чем просто переменные.
Пользовательские свойства CSS позволяют:
- Назначьте произвольные значения свойству с именем по вашему выбору
- Используйте функцию
var()
, чтобы использовать эти значения в других свойствах.
Несмотря на то, что поддержка пользовательских свойств CSS на данный момент представляет собой несколько тернистый путь, и некоторые браузеры поддерживают их с помощью флагов, которые необходимо активировать или установить в значение true заранее, ожидается, что их поддержка значительно увеличится в будущем, поэтому важно понимать как их использовать и использовать. 1
В этой статье вы узнаете, как можно использовать пользовательские свойства CSS, чтобы сделать ваши таблицы стилей немного более динамичными, возможно, сделав этот дополнительный шаг Sass/LESS в конвейере ресурсов устаревшим.
Оригинальная и менее мощная переменная CSS
Прежде чем мы начнем обсуждать пользовательские свойства CSS, следует отметить, что уже давно в CSS есть своего рода переменная, и это ключевое слово currentColor
. Эта редко используемая, но широко поддерживаемая переменная относится к текущему значению цвета элемента. Его можно использовать в любом объявлении, которое принимает значение color
, и оно отлично каскадируется.
Давайте рассмотрим пример:
.element { color: blue; border: 2px solid currentColor; /* Sets a solid, 2px wide, blue border to the element */ }
В дополнение к каскадированию это также может привести к следующему:
.element span { background: currentColor; /* Sets a blue background color for every span child of .element, unless a color property is declared in this same block */ } .element span.red { color: red; /* Sets a red background color for every span child of .element that has the class .red, since currentColor is applied to the background of every span child of .element no matter if they have the .red class or not */ }
Основная проблема с currentColor
, помимо того факта, что она не была в спецификации как переменная как таковая, заключается в том, что она принимает только значение свойства цвета, что в некоторых случаях может затруднить работу с ней.
Полноценные переменные CSS
Одним из основных преимуществ использования пре-/постпроцессоров CSS является то, что они позволяют сохранять значения в ключевом слове и при необходимости привязывать их к определенному селектору.
После долгих просьб разработчиков был написан черновой вариант интерпретации нативных переменных для CSS. Формально они называются пользовательскими свойствами CSS, но иногда их также называют переменными CSS.
Текущая спецификация нативных пользовательских свойств CSS охватывает все то же поведение, что и переменные пре-/постпроцессора. Это позволяет вам сохранять цветовые коды, размеры со всеми известными единицами измерения или только целыми числами, если это необходимо (например, когда вам нужно использовать один и тот же делитель или множитель).
Синтаксис пользовательских свойств CSS немного странный по сравнению с другими языками, но он имеет большой смысл, если вы сравните их синтаксис с другими функциями в той же экосистеме CSS:
:root { --color-black: #2e2e2e; } .element { background: var(--color-black); }
Теперь вы можете подумать: «Что это за синтаксис!?»
Что ж, Леа Веру объясняет причину этого синтаксиса «тире-тире» с абсолютной простотой, как она говорит в своем потрясающем выступлении «Переменные CSS»: var(–subtitle):
Они работают точно так же, как и любое другое свойство CSS […]. Так много людей спрашивают меня, почему мы не использовали [знак доллара] или что-то в этом роде, и причина, по которой мы не использовали [знак доллара], заключается в том, что мы хотим, чтобы люди могли использовать как SASS, так и переменные препроцессора и CSS-переменные. Это разные вещи, они достигают разных целей, есть вещи, которые вы можете делать с переменными CSS, которые вы абсолютно не можете делать с SASS, и есть вещи, которые вы можете делать с переменными SASS, но не можете делать с переменными CSS, поэтому мы хотим люди могут использовать их оба в одной и той же таблице стилей, поэтому вы можете представить синтаксис тире-тире как свойство префикса с пустым префиксом.
Мы можем получить значение пользовательского свойства с помощью функции var()
, которую мы можем использовать везде, кроме селекторов, имен свойств или объявлений медиа-запросов.
Стоит отметить, что хотя переменные пре/постпроцессора используются только во время компиляции, переменные CSS можно использовать и обновлять динамически. Что это значит? Это означает, что они сохраняются в фактической таблице стилей CSS. Таким образом, представление о том, что они являются переменными, останется даже после того, как таблицы стилей будут скомпилированы.
Чтобы было понятнее, позвольте мне проиллюстрировать ситуацию на нескольких примерах. Следующий блок кода является частью таблицы стилей SASS:
:root { $value: 30px; } @media screen and (min-width: 768px) { $value: 60px; } .corners { border-radius: $value; }
Этот фрагмент объявлений и правил SASS компилируется в CSS следующим образом:
.corners { border-radius: 30px; }
Вы можете видеть, что как свойства внутри :root
, так и media
-запрос теряются после компиляции, потому что переменные SASS не могут существовать внутри файла CSS (или, если быть более точным, они могут принудительно существовать в файле CSS, но игнорируются). так как часть их синтаксиса является недопустимым CSS), поэтому значение переменной не может быть впоследствии обновлено.

Теперь давайте рассмотрим тот же случай, но примененный с использованием только переменных CSS без применения пре/постпроцессора CSS (т. е. без какой-либо транспиляции или компиляции):
:root { --value: 30px; } @media screen and (min-width: 768px) { --value: 60px; } .corners { border-radius: var(--value); }
Очевидно, что ничего не меняется, поскольку мы ничего не компилировали/транспилировали, а значение пользовательского свойства может обновляться динамически. Так, например, если мы изменим значение --value
с помощью чего-то вроде JavaScript, значение будет обновляться в каждом случае, когда оно вызывается с помощью функции var().
Возможности настраиваемых свойств делают эту функцию настолько мощной, что вы даже можете делать такие вещи, как автопрефикс.
Леа Веру подает пример, используя свойство clip-path
. Мы начинаем с установки значения свойства, которое мы хотим использовать в качестве префикса, в initial
, но используем пользовательское свойство, а затем переходим к установке значения каждого свойства с префиксом в значение пользовательского свойства:
* { --clip-path: initial; -webkit-clip-path: var(--clip-path); clip-path: var(--clip-path); }
После этого останется только изменить значение пользовательского свойства внутри селектора:
header { --clip-path: polygon(0% 0%, 100% 0%, 100% calc(100% - 2.5em), 0% 100%); }
Если вы хотите узнать об этом немного больше, ознакомьтесь с полной статьей Леа об автопрефиксировании с помощью переменных CSS.
Пуленепробиваемые пользовательские свойства CSS
Как уже упоминалось, браузерная поддержка пользовательских свойств CSS по-прежнему в значительной степени нестандартна. Итак, как это можно преодолеть?
Именно здесь в игру вступает PostCSS и его плагин postcss-css-variables.
Если вам интересно, что такое PostCSS, прочтите мою статью PostCSS: новая дата запуска SASS и вернитесь к ней, когда закончите. После этого у вас будет базовое представление о том, что можно делать с помощью этого замечательного инструмента, и вы не будете чувствовать себя дезориентированным при чтении остальной части статьи.
С postcss-css-variables
и его параметром preserve
, установленным в true, мы можем сохранить все объявления функций var()
в выходных данных и иметь вычисленное значение в качестве резервного объявления. Он также сохраняет вычисленные объявления --var
. Имейте в виду, что с помощью этого плагина PostCSS пользовательские свойства могут динамически обновляться после процесса транспиляции, но резервные значения останутся прежними, если только они не будут специально выбраны и явно изменены по отдельности.
Если вы ищете способ использования переменных CSS без пре-/постпроцессора, вы всегда можете проверить текущую поддержку вручную с помощью правила CSS @support
и применить правильный запасной вариант, когда поддержка неоднородна или отсутствует. Например:
:root { --color-blue: #1e90ff; /* hex value for dodgerblue color */ } .element { background: var(--color-blue); } @supports (not(--value: 0)) { /* CSS variables not supported */ .element { background: dodgerblue; } }
Изменение значения пользовательского свойства с помощью JavaScript
На протяжении всей этой статьи я упоминал, что переменные можно обновлять с помощью JavaScript, так что давайте углубимся в это.
Допустим, у вас есть светлая тема и вы хотите переключить ее на темную тему, предполагая, что у вас есть некоторый CSS, подобный следующему:
:root { --text-color: black; --background-color: white; } body { color: var(--text-color); background: var(--background-color); }
Вы можете обновить пользовательские свойства --text-color
и --background-color
, выполнив следующие действия:
var bodyStyles = document.body.style; bodyStyles.setProperty('--text-color', 'white'); bodyStyles.setProperty('--background-color', 'black');
Интересные варианты использования
За годы разработки и обсуждения спецификаций пользовательских свойств CSS появилось несколько интересных вариантов использования. Вот несколько примеров:
Темы: использование набора тем для сайта довольно просто при реализации переменных CSS. Хотите светлую или темную вариацию вашего текущего стиля? Просто измените значение некоторых пользовательских свойств с помощью JavaScript, и все готово.
Настройка интервалов: нужно точно настроить интервалы сайта, скажем, желоб между столбцами? Измените значение одной переменной CSS и посмотрите, как это изменение отразится на всем сайте.
Полностью динамические функции calc(): теперь у вас могут быть полностью динамические функции calc()
с использованием настраиваемых свойств внутри этих функций, что устраняет необходимость выполнять сложные или эфемерные вычисления внутри JavaScript, а затем вручную обновлять эти значения в каждом экземпляре.
Вдохните новую жизнь в ваши файлы CSS
Пользовательские свойства CSS — это мощный и инновационный способ вдохнуть больше жизни в ваши таблицы стилей, впервые вводя в CSS полностью динамические значения.
Спецификация в настоящее время находится в статусе кандидата в рекомендации, а это означает, что стандартизация не за горами, и это хороший повод углубиться в эту функцию и получить от нее максимальную отдачу.
Примечание. Как указала Леа Веру 22 апреля, пользовательские свойства теперь поддерживаются по умолчанию почти во всех основных браузерах без необходимости переключать флаг. Его использование для производства безопасно, если не требуется поддержка старых версий браузеров.