Переменные в CSS или на английском CSS Custom Properties, что в переводе звучит, как пользовательские свойства CSS, - это специальные css-свойства, которые позволяют изменять значения любых других css-свойств динамически. CSS переременные подобны переменным в JavaScript. Сейчас css-переменные поддерживаются всеми современными браузерами. Можно сказать, что их появление было продиктовано еще препроцессорами, и то, что они были добавлены в спецификацию CSS - большой шаг вперед.

Переменные в CSS, или пользовательские свойства,  имеют огромный потенциал для изменения кода и структуры CSS. Давайте рассмотрим стратегии получения максимальной пользы от переменных CSS.

Схожесть css-переменных с переменными в препроцессорах

Пользовательские свойства немного похожи на переменные в препроцессорах, но имеют некоторые важные отличия. Первое и самое очевидное отличие - это синтаксис.

В синтаксисе SASS (SCSS) мы используем символ доллара для обозначения переменной:

Для Less нужно использовать символ @ :

Однако, препроцессорные переменные имеют некоторые ограничения:

Поэтому стоит изучить, что такое переменные CSS, и затем использовать их в коде.

CSS-переменные имеют синтаксис, похожий на переменные в SASS или Less, и используют префикс  в виде 2-х дефисов:

Значение свойства может быть любым допустимым значением CSS: цветом, строкой, значением макета, даже выражением.

Чтобы добавить использование переменной в код, необходимо записать так:

Еще несколько вариантов назначения css-переменных. Первый из них подразумевает использование глобальной видимости переменных, которые назначаются для :root:

Что касается элемента :root, то в HTML это то же самое, что и корневой тег html, но с более высокой специфичностью.

Для использования CSS-переменных необходимо  указать в соответствующем свойстве функцию var() с нужной переменной в скобках:

Вы можете объявлять переменные внутри любого элемента. Тогда они будут привязаны к этому элементу и его дочерним элементам. Использовать переменные можно следующим образом:

Результат:

Тестовый div

В примере ниже мы используем переменную из класса .box в классе .my-test, в который вложен .box. И не увидим, что эта переменная не применилась, т.к. для родительского .my-test она не видна.

Результат работы переменной не виден:

Тестовый div

css-переменная для родительского элементаНа скриншоте видно, что в свойстве переменная выделена серым цветом. Это значит, что она не была найдена и использована браузером.

Для вложенного элемента цвет переменной в инспекторе свойств другой - и мы видим на странице, что к нему добавилась точечная рамка.

css-переменная для дочернего элемента

Особенности объявления css-переменных и их использования

Функция var() - это удобный способ предоставить значение по умолчанию. Вы можете сделать это, если не уверены, определено ли настраиваемое свойство и хотите ли вы указать значение, которое будет использоваться в качестве резерва. Это можно сделать легко, передав второй параметр функции:

Кроме того, вы можете повторно использовать другие переменные для объявления новых:

Арифметические операции: +, -, * и функция calc()

Поскольку мы привыкли к препроцессорам и другим языкам, мы хотим иметь возможность использовать базовые операторы при работе с переменными. Для этого CSS предоставляет функцию calc(), которая заставляет браузер пересчитать выражение после внесения каких-либо изменений в значение настраиваемого свойства:

Вы можете столкнуться с проблемами, если попытаетесь использовать значение без единицы. В этой ситуации вам не обойтись без функции  calc() -  она ваш друг, потому что без нее код не будет работать:

Рассмотрим пример, в котором мы можем изменить размер шрифта кнопок, исходя из одной переменной и используя функцию calc() для расчета других величин на основе нашей единственной переменной:

Попробуйте самостоятельно изменить шрифт, изменяя значения в CSS.

See the Pen Размер кнопок в зависимости от css-переменной by Elen (@ambassador) on CodePen.

Области видимости и наследование

Прежде чем говорить о областях пользовательских свойств CSS, давайте вспомним области JavaScript и препроцессоры, чтобы лучше понять различия.

Мы знаем, что, например, с переменными JavaScript, которые определяются ключевым словом var, область действия ограничена функциями.

Мы имеем аналогичную ситуацию с let и const, но они являются локальными переменными масштаба блока.

Замыкание в JavaScript - это функция, которая имеет доступ к внешним (охватывающим) функциям - цепочке областей. Замыкание имеет три цепочки областей и имеет доступ к следующему:

  • его собственная область видимости (т. е. переменные, определенные между его фигурными скобками)
  • переменные внешней функции,
  • глобальные переменные.

Замыкание JS

История с препроцессорами схожа. Давайте используем SASS в качестве примера, потому что это, вероятно, самый популярный препроцессор сегодня. С SASS мы имеем два типа переменных: локальные и глобальные.

Глобальная переменная может быть объявлена ​​вне любого селектора или конструкции (например, как mixin). В противном случае переменная будет локальной.

closure-scss-opt

Любые вложенные блоки кода могут обращаться к окружающим переменным (как в JavaScript).

Это означает, что в SASS области действия переменной полностью зависят от структуры кода.

Однако пользовательские свойства CSS наследуются по умолчанию, и, как и другие свойства CSS, они каскадные.

Вы также не можете иметь глобальную переменную, которая объявляет пользовательское свойство вне селектора - это не допустимый CSS. Глобальная область действия для пользовательских свойств CSS на самом деле является корневой областью действия, после чего свойство доступно глобально.

Динамическое изменение css-переменных

Давайте использовать наши знания синтаксиса и адаптировать пример SASS к HTML и CSS. Мы создадим демонстрационную версию, используя собственные пользовательские свойства CSS. Во-первых, HTML:

Посмотрите на результат:

global
enclosing
closure

На скриншоте мы можем увидеть размер шрифта в классе .closure на основе вычисленных свойств.

Рассчетное значение свойства

Изменения в пользовательских свойствах немедленно применяются ко всем экземплярам.

Интересно, что в CSS вы можете изменить значение переменной уже после того, как она была использована для расчета значения свойства, и при этом вычисленное значение изменяется. Рассмотрим это на примере расчета размера шрифта из предыдущего блока кода и увидим, что значение размера шрифта пересчитывается из измененного значения --closureVar в 50px:

global
enclosing
closure

Скриншот с вычисленными значениями в Инспекторе свойств: 80px вместо 60px из предыдущего кода.

Измененное значение css-переменной при расчете свойстваВ SASS или LESS это бы не получилось. Это первое огромное отличие: если вы переназначите значение пользовательского свойства, браузер пересчитает все переменные и выражения calc(), где они были применены.

Препроцессоры не знают о структуре DOM

Предположим, что мы хотим использовать размер шрифта по умолчанию для блока, кроме случаев, когда присутствует выделенный класс. Тогда нам необходимо указать 2 переменные в скобках через запятую: сначала желаемое значение, затем значение по умолчанию.

Вот HTML- и CSS-код:

Поскольку второй элемент HTML с классом default имеет также класс highlighted, свойства для класса highlighted будут применены к этому элементу.

В данном случае это означает, что css-переменная -–highlighted-size: 30px; будет применена в нижнем div-е, и назначаемое свойство font-size будет использовать именно --highlighted-size.

Пример вживую:

default
default highlighted

Если аналогичный пример мы напишем в SASS, то получим несколько иной результат:

See the Pen Font-size with SASS by Elen (@ambassador) on CodePen.

Это происходит потому, что все вычисления и обработка SASS происходят во время компиляции, и, конечно, он ничего не знает о структуре DOM, полностью полагаясь на структуру кода.

В отличие от SASS, пользовательские свойства обладают преимуществами области видимости переменных и добавляют обычный каскад CSS-свойств в зависимости от структуры DOM и следуя тем же правилам, что и другие свойства CSS.

Отсюда вывод: css-переменные знают структуру DOM и являются динамическими.

Ключевые слова и свойство all для CSS-переменных

Пользовательские свойства CSS подчиняются тем же правилам, что и другие свойства CSS. Это означает, что вы можете назначить им любое из общих ключевых слов CSS:

  • inherit  (унаследовать). Это ключевое слово CSS применяет значение родительского элемента;
  • initial (начальное) - используется то значение свойства, которое определено в спецификации CSS (пустое значение или ничего в некоторых случаях );
  • unset (снять) - устанавливает значение свойства как inherit, если свойство наследуется от своего родителя, в противном случае значение устанавливается как initial.
  • revert (возврат) -  сбрасывает свойство к значению по умолчанию, установленному таблицей стилей браузера пользователя (пустое значение в случае пользовательских свойств CSS). Пока имеет ограниченную поддержку браузерами по данным caniuse.com.

Пример:

Давайте рассмотрим другой случай. Предположим, что вы хотите создать компонент и хотите быть уверенным, что другие стили или пользовательские свойства не будут применены к нему непреднамеренно (в таком случае обычно используется модульное решение CSS  для стилей).

Но теперь есть другой способ: использовать css-свойство all. Это сокращение сбрасывает все свойства CSS. То есть не нужно перечислять весь набор сбрасываемых свойств, а написать следующее:

Это сбросит все стили для нашего компонента.

К сожалению, ключевое слово all не сбрасывает пользовательские свойства (css-переменные). Таким образом, в будущем полный сброс может быть сделан следующим образом:

Варианты использования css-переменных

Есть много вариантов использования пользовательских свойств. Рассмотрим самые интересные из них.

Эмулировать несуществующие правила CSS

Имя этих CSS-переменных - «пользовательские свойства», так почему бы не использовать их для эмуляции несуществующих свойств?

Их много: translateX/Y/Z, background-repeat-x/y (все еще не совместимы с браузерами), box-shadow-color.

Давайте попробуем заставить последний работать. В нашем примере давайте изменим цвет рамки тени при наведении. Мы просто хотим следовать правилу DRY (не повторяться), поэтому вместо того, чтобы повторять все значение box-shadow в разделе :hover, мы просто изменим его цвет. Пользовательские свойства для спасения:

Посмотрим на результат:

Меняем цвет тени

Можно использовать переменные для добавления изображений, в том числе, и фоновых:

See the Pen CSS custom-properties via attribute by Burmese Potato (@BurmesePotato) on CodePen.

Цветовые схемы

Один из наиболее распространенных вариантов использования пользовательских свойств - для цветовых схем в приложениях. Пользовательские свойства были созданы для решения именно такой проблемы. Итак, давайте предоставим простую цветовую схему для компонента (те же шаги могут быть выполнены для приложения).

Вот код для нашего компонента кнопки:

Давайте предположим, что мы хотим инвертировать цветовую тему.

Первым шагом будет расширение всех цветовых переменных до пользовательских свойств CSS и перезапись нашего компонента. Итак, используем ряд переменных и запишем свойства с их использованием.  Результат будет таким же:

button

В этом коде есть все переменные, которые нужны для переопределения цветов на инвертированные значения. Мы могли бы, например, добавить класс inverted в HTML (скажем, к элементу section) и изменить цвета, когда он применяется:

Попробуйте сами с помощью примера ниже:

See the Pen Инвертируем цвета с помощью css-переменных by Elen (@ambassador) on CodePen.

Такое поведение не может быть достигнуто в препроцессоре CSS без дублирования кода. С препроцессором вам всегда нужно переопределять фактические значения и правила, что всегда приводит к дополнительному CSS.

Благодаря CSS-переманным решение максимально чистое, а копирование и вставка исключаются, поскольку переопределяются только значения переменных.

Использование цветовых функций

Для создания цветовых схем в препроцессорах можно использовать специальные функции для затемнения, осветления или обесцвечивания:

Мы можем заменить их css-переменными, используя функцию calc() и представление цвета в системе hls() или rgb(). Рассмотрим пример с цветами в системе rgb():

Пример с несколькими цветными кнопками:

See the Pen Цветовые изменения с помощью css-переменных by Elen (@ambassador) on CodePen.

Использование пользовательских свойств с JavaScript

Раньше для отправки данных из CSS в JavaScript нам часто приходилось прибегать к хитростям, записывая значения CSS через простой JSON в выводе CSS, а затем читая их из JavaScript.

Теперь мы можем легко взаимодействовать с CSS-переменными из JavaScript, читая и записывая их, используя хорошо известные методы getPropertyValue() и setProperty(), которые используются для обычных свойств CSS. Ниже приведены 2 функции, которые можно использовать для чтения и назначения css-переменных из JavaScript:

В примере ниже от автора Darko css-переменная --ratio используется для расчета размера фотографии для размещения фотогалереи из разноразмерных фотографий в одну строку:

See the Pen Google Photos grid (minimal JS) by Darko (@DarkoKukovec) on CodePen.

Еще мы можем использовать переменые для директивы @media. Предположим, у нас есть список значений медиа-запроса:

Поскольку мы хотим использовать их только в JavaScript - например, в Window.matchMedia() - мы можем легко получить их из CSS:

Пример изменения css-свойств с помощью css-переменных и JavaScript

See the Pen Update CSS Variables with JS by Elen (@ambassador) on CodePen.

В примере ниже от Lisi вы найдете использование множества переменных и в CSS, и в JavaScript.

See the Pen Single Div Animation by Lisi (@lisilinhart) on CodePen.

Пример переключения светлой/темной темы с помощью CSS-переменных

Автор Joe. При переключении мы видим анимацию.

See the Pen Article Toggle by Joe (@dope) on CodePen.

На основе статей It's Time To Start Using CSS Custom Properties и A Strategy Guide To CSS Custom Properties

Автор: Админ

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *