Как объявить и использовать переменную CSS
Переменная CSS, официально custom property (пользовательское свойство), это свойство, имя которого начинается с --. Объявите ее один раз, обычно в :root, чтобы ее унаследовала вся страница, и читайте где угодно через var().
Измените --brand на #16a34a, и рамка карточки и кнопка поменяются вместе. В этом весь смысл: одно значение, одно место для правки. Переменные сочетаются и с calc(), как показывают боковые отступы кнопки.
Синтаксис
:root {
--name: value; /* declare */
}
.element {
color: var(--name); /* use */
color: var(--name, #111827); /* use, with a fallback */
padding: calc(var(--space) * 2); /* compute with it */
}
| Правило | Подробности |
|---|---|
| Имя | Начинается с --, затем буквы, цифры, - или _. Регистр важен: --Brand это не --brand. |
| Значение | Почти что угодно: цвет, длина, список, строка. Оно не проверяется, пока его не используют. |
| Где объявлять | В любом правиле. :root для глобальных, селектор компонента для локальных значений. |
| Наследование | Пользовательские свойства наследуются, поэтому дочерний элемент видит значения предков. |
Где работает var() | Только в значениях свойств, не в селекторах, не в именах свойств и не в условиях @media. |
:root соответствует элементу <html>. Его используют вместо html, потому что специфичность у него как у класса, а по соглашению он обозначает «глобальные настройки».
Область видимости: переопределение переменной в компоненте
Переменные наследуются, поэтому повторное объявление на элементе меняет ее для этого элемента и всего, что внутри. Правило, которое использует переменную, остается прежним.
Варианты задают только переменную, а не саму рамку. Четвертый вариант добавляется одной строкой.
Значения по умолчанию
var(--name, fallback) использует запасное значение, когда переменная не определена ни на элементе, ни на одном предке. Все после первой запятой считается запасным значением, поэтому в нем самом могут быть запятые (var(--font, Georgia, serif)), и это может быть другой var().
Изменение переменных через JavaScript: переключатель темы
JavaScript может задать переменную на любом элементе через style.setProperty(). Задайте ее на document.documentElement (элемент <html>), и за ней последует вся страница. Чаще переключают класс, который переопределяет переменные:
Значение переменной читается через getComputedStyle(element).getPropertyValue('--text'). Учтите, что setProperty записывает встроенный стиль на <html>, который сильнее класса .dark, поэтому после нажатия второй кнопки цвет текста остается прежним в обеих темах, пока встроенное значение не удалят через root.style.removeProperty('--text').
Передача значений из HTML
Переменная в атрибуте style это самый чистый способ передать таблице стилей данные конкретного элемента. Дизайн остается в CSS, а HTML дает только число.
calc(var(--value) * 1%) превращает простое число в проценты. Переменные могут меняться и внутри медиазапроса: @media (min-width: 900px) { :root { --space: 20px; } } увеличивает на широких экранах все отступы, которые читают --space.
Ловушка невалидного значения
Браузер не может заранее знать, подходит ли значение переменной для свойства, которое ее использует. Если не подходит, свойство не откатывается к предыдущему объявлению в правиле. Оно становится невалидным на этапе вычисления значения и ведет себя так, будто ему задано unset: наследуемые свойства берут значение родителя, остальные свое начальное значение.
Текст наследует 16px от <body>, а border-width возвращается к начальному значению medium, которое браузеры рисуют как 3px. Без переменных невалидное объявление отбрасывается и предыдущее остается в силе; с переменными для этого уже поздно. Запасное значение не помогает, когда переменная определена, но неверна: оно только для неопределенной переменной.
Переменные CSS и переменные Sass
| Переменные CSS | Переменные Sass | |
|---|---|---|
| Синтаксис | --brand: #2563eb; и var(--brand) | $brand: #2563eb; |
| Когда вычисляются | В браузере, на лету | При сборке, в результат не попадают |
| Разные значения у элементов | Да, через наследование | Нет |
| Смена через класс или медиазапрос | Да | Нет |
| Смена из JavaScript | Да | Нет |
| Использование в селекторах и условиях media | Нет | Да |
Они работают вместе: многие проекты используют Sass для логики на этапе сборки и выдают CSS-переменные для всего, что должно меняться темой.
Частые ошибки
- Забытые два дефиса.
var(brand)и--brand, объявленная как-brand, не работают. - Переменная в медиазапросе.
@media (min-width: var(--bp))невалидно. В условиях media нужны буквальные значения. - Ожидание, что предыдущее объявление переживет невалидную переменную. Не переживет; смотрите ловушку выше.
- Неправильное сочетание единиц.
--gap: 10;и затемmargin: var(--gap)pxне дают10px. Используйтеcalc(var(--gap) * 1px)или храните10px. - Объявление не на том элементе. Переменную, объявленную на
.card, не видят его соседи и родитель; общие значения объявляйте на:root.
Часто задаваемые вопросы
Как объявить переменную CSS?
Запишите внутри правила свойство, имя которого начинается с двух дефисов, для глобального значения обычно в :root: :root { --brand: #2563eb; }. Читайте ее где угодно через var(--brand), например color: var(--brand);.
Что такое :root в CSS?
:root это псевдокласс, который соответствует корневому элементу документа, в HTML-странице это <html>. Объявленные в нем переменные наследуют все элементы. Его специфичность как у класса, поэтому он сильнее простого селектора html.
Как задать значение по умолчанию для переменной CSS?
Передайте в var() второй аргумент: color: var(--accent, #2563eb);. Запасное значение используется, когда --accent не определена на элементе и его предках. Оно не используется, если переменная определена, но ее значение невалидно для свойства.
Как изменить переменную CSS через JavaScript?
Вызовите setProperty у стиля элемента: document.documentElement.style.setProperty('--brand', '#16a34a'). Все правила с var(--brand) обновятся сразу. Текущее значение читается через getComputedStyle(el).getPropertyValue('--brand').
Чем переменные CSS отличаются от переменных Sass?
Переменные Sass заменяются значениями при компиляции таблицы стилей, поэтому в браузере они меняться не могут. Переменные CSS живут в браузере: наследуются, могут отличаться у разных элементов, реагируют на медиазапросы и классы и меняются из JavaScript.
Учитывается ли регистр в именах переменных CSS?
Да. --Brand и --brand это две разные переменные, в отличие от имен обычных свойств вроде color, где регистр не важен.