CSS Variables или CSS Custom Properties уже давно используются в разработке и поддерживаются большинством популярных браузеров. Если у вас нет обязательного требования разрабатывать под IE, то вполне вероятно, вы уже успели оценить их преимущества.
По этой теме написано множество статей, но я сфокусируюсь на том, чтобы показать распространенные кейсы по использованию, которые сам применял на практике. Будет мало теории, но много кода.
:root {
/* Определение переменной внутри корневого элемента */
--color: green;
}
body {
/* Определение переменной внутри селектора */
--font: 15px;
background-color: var(--color);
font-size: var(--font);
}
body {
--color: green;
}
button {
color: var(--color);
}
button:hover {
--color: red;
}
Второй пример показывает переопределение переменной в @media выражении. К сожалению, мы не можем вынести 1024px в переменную и использовать ее в @media - это является одним из ограничений CSS переменных.
:root {
--color: green;
}
body {
background-color: var(--color);
}
@media (max-width: 1024px) {
:root {
--color: red;
}
}
:root {
--color-green: green;
--color-blue: blue;
--color-red: red;
}
body {
color: var(--color-green, blue);
color: var(--color-green, var(--color-blue));
color: var(--color-green, var(--color-blue, var(--color-red, red)));
}
:root {
--color1: var(--color2);
--color2: var(--color3);
--color3: red;
}
body {
background-color: var(--color1);
}
На выходе получим результирующее значение в той единице измерения, на которую умножили.
В примере показано, как перемножается 2 на 10px и в итоге получается 20px. Не важно, используем мы для этого обычные значения или CSS-переменные - результат будет одинаковый:
:root {
--increment: 2;
--size: 10px;
}
body {
/* Будет 20px; */
font-size: calc(var(--increment) * var(--size));
}
К примеру, у нас есть переменная --font: 20. Но без указания единицы измерения мы не сможем ее корректно использовать в font-size.
Это можно решить с помощью calc(). Для преобразования числа в px, к примеру, достаточно умножить число на 1px в calc():
:root {
--font: 20;
}
div {
/* Будет 20px; */
font-size: calc(var(--font) * 1px);
}
Вот стандартный пример по использованию hex-цвета для определения значения переменной:
:root {
/* hex формат */
--color-blue: #42c8f5;
}
body {
color: var(--color-blue);
}
Часто бывает, что для цвета нужно задавать различную прозрачность. В CSS для этого есть:
При использовании переменных, удобнее это делать функцией rgba(), которая принимает 4 числовых значения для:
Поэтому, задание в переменной значения цветов для Red, Green, Blue - вполне допустимо.
:root {
/* Указание значений цветов: Red Green Blue */
--color-blue--rgb: 66, 200, 245;
}
Вызовем функцию rgba() с переменной --color-blue--rgb. Для rgba() не хватает четвертого аргумента задающего прозрачность - добавим его через запятую:
body {
background-color: rgba(var(--color-blue--rgb), 0.7);
}
На выходе собираются аргументы для rgba(): значения из переменной и альфа-канала.
По итогу получаем цвет:
body {
background-color: rgba(66, 200, 245, 0.7);
}
Использование hsla()
Кроме rgba() можно использовать и hsla(). Это не так удобно, но как вариант, можно попробовать.
Идея следующая:
--hue: 285;
--saturation: 100%;
--lightness: 60%;
--opacity: 0.7;
}
body {
/* Переопределяем значение для --hue */
--hue: 400;
background-color: hsla(
var(--hue),
var(--saturation),
var(--lightness),
var(--opacity)
);
}
На выходе получаем цвет:
body {
background-color: hsla(400, 100%, 60%, 0.7);
}
Итак, имеем SVG-элемент на странице, у которого в fill указана переменная --color:
<svg class="icon">
<circle cx="50" cy="50" r="50" fill="var(--color)" />
</svg>
И саму переменную --color в CSS:
:root {
--color: green;
}
Значение переменной можно переопределять при необходимых условиях: например, при событии hover на SVG:
.icon:hover {
--color: pink;
}
Рассмотрим, как можно работать с CSS переменными через JavaScript:
В CSS у нас есть 2 переменные:
:root {
--color: green;
}
А вот код на JavaScript:
// Получаем корневой элемент в DOM
const root = document.querySelector(':root');
// Получаем "Вычисленные свойства"
const rootStyles = getComputedStyle(root);
// Получаем значение переменной по ее названию
const color = rootStyles.getPropertyValue('--color'); // => 'green'
// Изменяем значение переменной
root.style.setProperty('--color', '#88d8b0');
// Удаляем CSS переменную
root.style.removeProperty('--color');
Для примера, я показал все возможные действия с переменными: чтение, изменение, удаление. Использовать операции можно по необходимости.
HTML-код:
<h1>Hello</h1>
CSS-код:
h1 {
font-size: 5rem;
}
Единицы измерения можно подразделить на абсолютные и относительные:
Небольшую демку по изменению цветовой схемы можно посмотреть здесь.
@supports ( (--a: 0) ) {
/* Стили с поддержкой переменных */
}
@supports ( not (--a: 0) ) {
/* Стили без поддержки переменных */
}
Из JavaScript:
if (window.CSS && window.CSS.supports && window.CSS.supports('--a', 0)) {
// Сценарии с поддержкой переменных
} else {
// Сценарии без поддержки переменных
}
По этой теме написано множество статей, но я сфокусируюсь на том, чтобы показать распространенные кейсы по использованию, которые сам применял на практике. Будет мало теории, но много кода.
Варианты использования
1. Определение переменных
Начнём с базовых вещей, а именно: как определять переменные. Стоит помнить, что их можно определить как в корневом элементе :root (переменные будут доступны по всему приложению), так и внутри любого селектора (будут доступны только для выбранного элемента и его дочерних элементов)::root {
/* Определение переменной внутри корневого элемента */
--color: green;
}
body {
/* Определение переменной внутри селектора */
--font: 15px;
background-color: var(--color);
font-size: var(--font);
}
2. Переопределение переменных
В примере показан кейс, когда при наведении на элемент, должен меняться цвет. Для этого мы переопределяем переменную --color по событию :hover:body {
--color: green;
}
button {
color: var(--color);
}
button:hover {
--color: red;
}
Второй пример показывает переопределение переменной в @media выражении. К сожалению, мы не можем вынести 1024px в переменную и использовать ее в @media - это является одним из ограничений CSS переменных.
:root {
--color: green;
}
body {
background-color: var(--color);
}
@media (max-width: 1024px) {
:root {
--color: red;
}
}
3. Локальный fallback
Представьте, что вы вызываете переменную --color-green, а ее не существует. Страшного не случится, но заданное CCS-свойство не отработает. Для подстраховки можно задать резервное значение вторым аргументом. Это значение также может быть CSS-переменной::root {
--color-green: green;
--color-blue: blue;
--color-red: red;
}
body {
color: var(--color-green, blue);
color: var(--color-green, var(--color-blue));
color: var(--color-green, var(--color-blue, var(--color-red, red)));
}
4. Привязка переменных
При объявлении переменных могут использоваться другие переменные::root {
--color1: var(--color2);
--color2: var(--color3);
--color3: red;
}
body {
background-color: var(--color1);
}
5. Переменные в calc()
В calc() можно перемножать числа со значениями в единицах измерения, н-р: px.На выходе получим результирующее значение в той единице измерения, на которую умножили.
В примере показано, как перемножается 2 на 10px и в итоге получается 20px. Не важно, используем мы для этого обычные значения или CSS-переменные - результат будет одинаковый:
:root {
--increment: 2;
--size: 10px;
}
body {
/* Будет 20px; */
font-size: calc(var(--increment) * var(--size));
}
К примеру, у нас есть переменная --font: 20. Но без указания единицы измерения мы не сможем ее корректно использовать в font-size.
Это можно решить с помощью calc(). Для преобразования числа в px, к примеру, достаточно умножить число на 1px в calc():
:root {
--font: 20;
}
div {
/* Будет 20px; */
font-size: calc(var(--font) * 1px);
}
6. Прозрачность в цветовых функциях
Задания цвета - самый распространенный кейс использования переменных.Вот стандартный пример по использованию hex-цвета для определения значения переменной:
:root {
/* hex формат */
--color-blue: #42c8f5;
}
body {
color: var(--color-blue);
}
Часто бывает, что для цвета нужно задавать различную прозрачность. В CSS для этого есть:
- rgba()
- hsla()
- hwb()
- #rrggbbaa hex color notation
При использовании переменных, удобнее это делать функцией rgba(), которая принимает 4 числовых значения для:
- Красного цвета
- Зеленого цвета
- Синего цвета
- Альфа-канала для задания прозрачности
Поэтому, задание в переменной значения цветов для Red, Green, Blue - вполне допустимо.
:root {
/* Указание значений цветов: Red Green Blue */
--color-blue--rgb: 66, 200, 245;
}
Вызовем функцию rgba() с переменной --color-blue--rgb. Для rgba() не хватает четвертого аргумента задающего прозрачность - добавим его через запятую:
body {
background-color: rgba(var(--color-blue--rgb), 0.7);
}
На выходе собираются аргументы для rgba(): значения из переменной и альфа-канала.
По итогу получаем цвет:
body {
background-color: rgba(66, 200, 245, 0.7);
}
Использование hsla()
Кроме rgba() можно использовать и hsla(). Это не так удобно, но как вариант, можно попробовать.
Идея следующая:
- Определяем переменные с базовыми значениями для основных параметров hsla(): --hue, --saturation, --lightness, --opacity.
- При использовании, указываем все базовые параметры в селекторе.
- Меняем один / несколько переменных в селекторе (изменения коснутся только данного селектора и его дочерних элементов).
--hue: 285;
--saturation: 100%;
--lightness: 60%;
--opacity: 0.7;
}
body {
/* Переопределяем значение для --hue */
--hue: 400;
background-color: hsla(
var(--hue),
var(--saturation),
var(--lightness),
var(--opacity)
);
}
На выходе получаем цвет:
body {
background-color: hsla(400, 100%, 60%, 0.7);
}
7. Переменные в SVG
С помощь переменных мы также можем изменять цвет внутри SVG: fill или stroke. Сложность заключается в том, что изображение SVG должно быть инлайново встроено на страницу, но при использовании сборщиков - это не проблема.Итак, имеем SVG-элемент на странице, у которого в fill указана переменная --color:
<svg class="icon">
<circle cx="50" cy="50" r="50" fill="var(--color)" />
</svg>
И саму переменную --color в CSS:
:root {
--color: green;
}
Значение переменной можно переопределять при необходимых условиях: например, при событии hover на SVG:
.icon:hover {
--color: pink;
}
Использование с JavaScript. API CSS Style Declaration
CSS переменные работают в runtime, в отличие переменных препроцессоров. Это значит, что мы можем получить к ним доступ в процессе работы приложения через JavaScript.Рассмотрим, как можно работать с CSS переменными через JavaScript:
В CSS у нас есть 2 переменные:
:root {
--color: green;
}
А вот код на JavaScript:
// Получаем корневой элемент в DOM
const root = document.querySelector(':root');
// Получаем "Вычисленные свойства"
const rootStyles = getComputedStyle(root);
// Получаем значение переменной по ее названию
const color = rootStyles.getPropertyValue('--color'); // => 'green'
// Изменяем значение переменной
root.style.setProperty('--color', '#88d8b0');
// Удаляем CSS переменную
root.style.removeProperty('--color');
Для примера, я показал все возможные действия с переменными: чтение, изменение, удаление. Использовать операции можно по необходимости.
Вычисленные свойства
В коде выше я затронул тему "Вычисленных свойств". Рассмотрим подробнее: для этого создадим небольшой пример:HTML-код:
<h1>Hello</h1>
CSS-код:
h1 {
font-size: 5rem;
}
Единицы измерения можно подразделить на абсолютные и относительные:
- Абсолютные - это пиксели (px), которые привязываются к разрешению экрана.
- Относительные (н-р: rem) формируются относительно заданного параметра.
- В секции Styles - значения в том виде, в котором мы их указали в CSS (относительные).
- В секции Computed - значения, приведенные к абсолютным единицам измерения. Функцией getComputedStyle в JavaScript мы как раз таки и получаем эти вычисленные значения.
Небольшую демку по изменению цветовой схемы можно посмотреть здесь.
Проверка поддержки переменных
Из CSS:@supports ( (--a: 0) ) {
/* Стили с поддержкой переменных */
}
@supports ( not (--a: 0) ) {
/* Стили без поддержки переменных */
}
Из JavaScript:
if (window.CSS && window.CSS.supports && window.CSS.supports('--a', 0)) {
// Сценарии с поддержкой переменных
} else {
// Сценарии без поддержки переменных
}
Достоинства и ограничения
Достоинства:- Работают в runtime, в отличие от переменных препроцессоров
- Можно обратиться из JavaScript
- В именах обычных свойств CSS: var(--side): 10px
- В значениях media-запросов: @media screen and (min-width: var(--desktop))
- В подстановке URL: url(var(--image))
- Нельзя сбрасывать значения всех переменных --: initial
Заключение
Использование CSS-переменных еще один шаг к отказу от препроцессоров. Ждем реализации миксинов @apply на CSS и CSS Nesting Module!Основные варианты использования CSS-переменных (Custom Properties)
CSS Variables или CSS Custom Properties уже давно используются в разработке и поддерживаются большинством популярных браузеров. Если у вас нет обязательного требования...
habr.com