Автор курса Нетологии «HTML-верстка» Стас Мельников рассказал о нюансах, которые могут усложнить работу с пользовательскими CSS-свойствами.
Мы привыкли, что встроенные CSS-свойства нечувствительны к регистру. Поэтому следующие способы объявления свойства
Пользовательские свойства, наоборот, чувствительны к регистру, поэтому в следующем примере создаются два разных пользовательских свойства:

Теперь рамка стала цветом #800080 (фиолетовый), а цвет текста — #27ae60 (зеленый).
У обычного CSS-свойства можно задать только разрешенные по стандарту значения. Согласно стандарту пользовательских свойств, в качестве значения можно использовать любое существующее корректное CSS-значение. Например, как у всех следующих пользовательских свойств:
Для примера зададим рамку с цветом #800080 для кнопки:

Помимо стандартных значений, можно задать одно пользовательское свойство в качестве значения для другого.
Результат ничем отличается от предыдущего, и у кнопки все так же рамка с цветом #800080.
Если у пользовательского свойства

Дело в том, что прежде чем браузер применит значение пользовательского свойства для встроенного свойства, он проверит его на корректность. Если значение доступно для встроенного свойства, то браузер применит его. А если нет, то установит для встроенного свойства значение по умолчанию.
В нашем случае 18px некорректное значение для встроенного свойства

Как видим, браузер применил значение #800080 для рамки. В этом примере я использовал полный синтаксис, чтобы установить рамку. Но мы можем использовать краткий, а именно свойство

Здесь нас ожидает еще один нюанс. В стандарте есть отдельный раздел, в котором описано поведение пользовательских свойств в такой ситуации. Согласно ему, если пользовательское свойство имеет некорректное значение для встроенного свойства, то это пользовательское свойство является невалидным, поэтому браузер проигнорирует встроенное свойство.
В нашем примере у встроенного свойства
Когда мы рассматривали пример с функцией
Но кроме него, функция

Когда браузер поймет, что разработчик не объявил значение для пользовательского свойства, то использует значение по умолчанию. Например значение #800080 (фиолетовый) для пользовательского свойства

Мы видим, что рамка и текст стали фиолетовыми. Но если навести на кнопку, то они станут зелеными. Это говорит о том, что браузер применил значение #27ae60 для пользовательского свойства, тем самым заменив значение по умолчанию.
Но это еще не все возможности функции
Но можно сделать по-другому. Функция
Внешне результат не изменится. Но теперь для изменения значения по умолчанию нужно сделать это только в одном месте, а не в нескольких, как раньше.
В CSS работает механизм наследования, который позволяет элементам наследовать свойства у родительских элементов. В этом плане пользовательские свойства ничем не отличаются от них. Для примера я напишу код, в котором пользовательское свойство

Посмотрев в инспектор, можно заметить надпись «Inherited from body», которая показывает нам, что пользовательское свойство было взято из элемента

В инспекторе видно, что пользовательское свойство
В стандарте CSS Custom Properties ввели особенный псевдокласс

В инспекторе мы можем увидеть, что объявленное пользовательское свойство применяется к элементу html. Но, кроме HTML-документа, псевдокласс

И здесь мы видим, что у корневого элемента SVG добавился псевдокласс
В этой статье мы познакомились с подводными камнями пользовательских свойств, которые могут сбить с толку. И соответственно, мы можем начинать использовать их. Поэтому в следующей статье я расскажу про практические трюки, которые использую в своих проектах.
Курсы «Нетологии» по теме:
Правила синтаксиса названий пользовательских свойств
Мы привыкли, что встроенные CSS-свойства нечувствительны к регистру. Поэтому следующие способы объявления свойства
border дадут одинаковый результат:button { BORDER: 2px solid #800080; } button { border: 2px solid #800080; }
Пользовательские свойства, наоборот, чувствительны к регистру, поэтому в следующем примере создаются два разных пользовательских свойства:
button { --NETOLOGY-BRAND-COLOR: #800080; --netology-brand-color: #27ae60; border: 2px solid var(--NETOLOGY-BRAND-COLOR); color: var(--netology-brand-color); }

Теперь рамка стала цветом #800080 (фиолетовый), а цвет текста — #27ae60 (зеленый).
Допустимые значения для пользовательских свойств
У обычного CSS-свойства можно задать только разрешенные по стандарту значения. Согласно стандарту пользовательских свойств, в качестве значения можно использовать любое существующее корректное CSS-значение. Например, как у всех следующих пользовательских свойств:
.element::before { --color: rgba(0, 0, 0, 1); --hex: #000000; --value: 20px; --number: 3; --text: "Hey, what's up?"; --keyword: currentColor; }
Для примера зададим рамку с цветом #800080 для кнопки:
button { --netologyBrandColor: #800080; border-width: 2px; border-style: solid; border-color: var(--netologyBrandColor); }

Помимо стандартных значений, можно задать одно пользовательское свойство в качестве значения для другого.
button { --netologyBrandColor: #800080; --buttonBorderColor: var(--netologyBrandColor); border-width: 2px; border-style: solid; border-color: var(--buttonBorderColor); }
Результат ничем отличается от предыдущего, и у кнопки все так же рамка с цветом #800080.
Если у пользовательского свойства
--netologyBrandColor будет некорректное значение для свойства border-color, например 18px, то рамка станет черной. button { --netologyBrandColor: 18px; --buttonBorderColor: var(--netologyBrandColor); border-width: 2px; border-style: solid; border-color: var(--buttonBorderColor); }

Дело в том, что прежде чем браузер применит значение пользовательского свойства для встроенного свойства, он проверит его на корректность. Если значение доступно для встроенного свойства, то браузер применит его. А если нет, то установит для встроенного свойства значение по умолчанию.
В нашем случае 18px некорректное значение для встроенного свойства
border-color, и поэтому браузер установит значение по умолчанию, т.е currentColor. Это очень легко проверить, задав для свойства color значение #800080:button { --netologyBrandColor: 18px; --buttonBorderColor: var(--netologyBrandColor); border-width: 2px; border-style: solid; border-color: var(--buttonBorderColor); color: #800080; }

Как видим, браузер применил значение #800080 для рамки. В этом примере я использовал полный синтаксис, чтобы установить рамку. Но мы можем использовать краткий, а именно свойство
border.button { --netologyBrandColor: 18px; --buttonBorderColor: var(--netologyBrandColor); border: 2px solid var(--buttonBorderColor); color: #800080; }

Здесь нас ожидает еще один нюанс. В стандарте есть отдельный раздел, в котором описано поведение пользовательских свойств в такой ситуации. Согласно ему, если пользовательское свойство имеет некорректное значение для встроенного свойства, то это пользовательское свойство является невалидным, поэтому браузер проигнорирует встроенное свойство.
В нашем примере у встроенного свойства
border в качестве одного из значений установлено пользовательское свойство --buttonBorderColor с некорректным значением 18px. Согласно описанному алгоритму, браузер просто проигнорировал свойство border, поэтому у элемента пропала рамка.Значение по умолчанию для пользовательских свойств
Когда мы рассматривали пример с функцией
var, то использовали только один параметр — название пользовательского свойства.button { --netologyBrandColor: #800080; border: 2px solid var(--netologyBrandColor); color: var(--netologyBrandColor); } button:hover { --netologyBrandColor: #27ae60; }
Но кроме него, функция
var может принимать и второй — значение по умолчанию. Для объявления значения по умолчанию нужно после названия пользовательского свойства поставить запятую и написать само значение.
Когда браузер поймет, что разработчик не объявил значение для пользовательского свойства, то использует значение по умолчанию. Например значение #800080 (фиолетовый) для пользовательского свойства
--netologyBrandColor.button { border: 2px solid var(--netologyBrandColor, #800080); color: var(--netologyBrandColor, #800080); } button:hover { --netologyBrandColor: #27ae60; }

Мы видим, что рамка и текст стали фиолетовыми. Но если навести на кнопку, то они станут зелеными. Это говорит о том, что браузер применил значение #27ae60 для пользовательского свойства, тем самым заменив значение по умолчанию.
Но это еще не все возможности функции
var. В предыдущим примере пользовательское свойство --netologyBrandColor используется два раза, соответственно, поэтому я установил два раза значение по умолчанию. Но можно сделать по-другому. Функция
var позволяет передавать другую функцию var, поэтому в качестве значе��ия по умолчанию можно задать другое пользовательское свойство. Я перепишу предыдущий пример с использованием пользовательского свойства --defaultButtonColor:button { --defaultButtonColor: #800080; border: 2px solid var(--netologyBrandColor, var(--defaultButtonColor)); color: var(--netologyBrandColor, var(--defaultButtonColor)); } button:hover { --netologyBrandColor: #27ae60; }
Внешне результат не изменится. Но теперь для изменения значения по умолчанию нужно сделать это только в одном месте, а не в нескольких, как раньше.
Наследование пользовательских свойств
В CSS работает механизм наследования, который позволяет элементам наследовать свойства у родительских элементов. В этом плане пользовательские свойства ничем не отличаются от них. Для примера я напишу код, в котором пользовательское свойство
--netologyBrandColor наследуется от родительского элемента body.body { --netologyBrandColor: #800080; } button { border: 2px solid var(--netologyBrandColor); color: var(--netologyBrandColor); } </td></tr>

Посмотрев в инспектор, можно заметить надпись «Inherited from body», которая показывает нам, что пользовательское свойство было взято из элемента
body. Но если для элемента button добавить пользовательское свойство --netologyBrandColor, то оно уже перекроет свойство из элемента body.body { --netologyBrandColor: #800080; } button { --netologyBrandColor: #27ae60; border: 2px solid var(--netologyBrandColor); color: var(--netologyBrandColor); }

В инспекторе видно, что пользовательское свойство
--netologyBrandColor у элемента button переопределило свойство --netologyBrandColor, которое мы указали для элемента body.Глобальные значения
В стандарте CSS Custom Properties ввели особенный псевдокласс
root, который позволяет указать пользовательские свойства, которые применяются к корневому элементу документа. Например, в HTML-документе к элементу html.:root { --netologyBrandColor: #800080; } button { border: 2px solid var(--netologyBrandColor); color: var(--netologyBrandColor); }

В инспекторе мы можем увидеть, что объявленное пользовательское свойство применяется к элементу html. Но, кроме HTML-документа, псевдокласс
root работает в SVG-документах. Например, я объявлю пользовательские свойства в теге style.<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 28" width="50" height="50"> <style> :root{ --iconColor: #ffcc00; --iconStroke: #000000; --iconStrokeWidth: 2px; } </style> <path stroke="var(--iconStroke)" stroke-width="var(--iconStrokeWidth)" fill="var(--iconColor)" d="M26 10.109c0 .281-.203.547-.406.75l-5.672 5.531 1.344 7.812c.016.109.016.203.016.313 0 .406-.187.781-.641.781a1.27 1.27 0 0 1-.625-.187L13 21.422l-7.016 3.687c-.203.109-.406.187-.625.187-.453 0-.656-.375-.656-.781 0-.109.016-.203.031-.313l1.344-7.812L.39 10.859c-.187-.203-.391-.469-.391-.75 0-.469.484-.656.875-.719l7.844-1.141 3.516-7.109c.141-.297.406-.641.766-.641s.625.344.766.641l3.516 7.109 7.844 1.141c.375.063.875.25.875.719z"/> </svg>

И здесь мы видим, что у корневого элемента SVG добавился псевдокласс
root. Соответственно, это доказывает, что псевдокласс root применяется не только к тегу html, а к любому корневому элементу.Заключение
В этой статье мы познакомились с подводными камнями пользовательских свойств, которые могут сбить с толку. И соответственно, мы можем начинать использовать их. Поэтому в следующей статье я расскажу про практические трюки, которые использую в своих проектах.
От редакции
Курсы «Нетологии» по теме:
- онлайн-профессия «Аналитик данных»
- онлайн-профессия «Data Scientist»
- онлайн-курс «Фронтенд-разработчик»
