Зачем нужны кастомные свойства и как они работают?
В языках программирования есть переменные: вы что-нибудь один раз объявляете, присваиваете значение, а потом снова и снова используете. Если значение переменной меняется, то оно меняется везде. Похоже на местоимения в языке: из предложения или абзаца всегда понятно, кто «мы» или что за «оно», мы их как будто объявили раньше и наверняка переопределим потом.
Но это языки программирования, а что со стилями? Вообще, декларативная природа CSS не подразумевает никаких переменных и соавтор CSS Берт Бос очень против, почитайте. Но жизнь внесла свои коррективы в изначальную идею, и переменные в стилях появились — слишком уж удобно было. Но сначала в препроцессорах.
Как работают препроцессоры? Вы пишете на каком-то языке, который внешне напоминает CSS, а иногда вообще не напоминает.
@mixin sass
@if &
&:hover
color: tomato
@else
a
color: plum
Потом это компилируется в настоящие стили. Переменные там — это такая сложная автозамена переменных на их значения. Sass, Less, Stylus, PostCSS-плагины — все они работают только так. Эти переменные существуют только в разработке, в браузере их уже нет.
.scss {
$variable: value;
color: $variable;
}
Если сравнить такое поведение с JavaScript, то становится очень обидно за CSS. В JS переменные живут прямо в браузере, их можно создавать и менять на лету. Тем не менее такие переменные и другие элементы программирования в CSS-препроцессорах получили огромную популярность. Уже почти не бывает больших проектов без препроцессоров.
К счаcтью нашлись люди, недовольные такими куцыми переменными. После ряда черновиков и вариаций синтаксиса, Таб Аткинс написал спецификацию полноценных CSS-переменных, точнее, кастомных свойств. Эти переменные поддерживаются уже в 70% браузеров по миру и сильно меняют принцип написания стилей.
Кастомные кто? Объясняю. Помните, я говорил, что CSS не очень-то готов к переменным? Чтобы сохранить синтаксическую совместимость со старыми браузерами и не противоречить модели языка, было решено сделать не просто переменные с долларом в начале, а механизм создания собственных свойств для нужд разработчика. Ещё их переводят как «пользовательские» свойства, но с этим возникает путаница: кто здесь пользователь, а кто здесь разработчик? Сразу скажу, синтаксис у них немножко странный, но вы поймёте почему.
Например, у нас сейчас есть свойство box-shadow
, чтобы отбрасывать тень. А раньше его не было, оно появилось первым в браузере Safari в 2008 году. Но появилось не просто так, а как -webkit-box-shadow
, с префиксом, начинающимся с дефиса. То есть разработчики движка WebKit придумали своё свойство. Только потом, когда оно стало частью стандарта и появилось в других браузерах, префикс убрали.
.shady {
-webkit-box-shadow: 0 0 0 4px tomato;
box-shadow: 0 0 0 4px tomato;
}
Теперь вы тоже можете создавать собственные свойства, только не нужно указывать между дефисами название движка: дефис, дефис, название свойства. Давайте создадим свойство --box-shadow-color
и зададим ему значение tomato
. Чтобы использовать это значение в коде, нужно передать его в функцию var()
.
.shady {
--box-shadow-color: tomato;
box-shadow: 0 0 0 5px var(--box-shadow-color);
}
Мы сейчас объявили новое свойство, которое потом можно повторно использовать снова и снова. А ещё свойства box-shadow-color
никогда не было в природе и чтобы менять тени, например, по наведению, приходилось переписывать box-shadow
целиком. А теперь по ховеру можно просто поменять значение переменной. Круто?
.shady {
--box-shadow-color: tomato;
}
.shady:hover {
--box-shadow-color: plum;
}
Если вы используете кастомное свойство, которое почему-то не было объявлено, то можно указать его значение по умолчанию, которое будет использовано в таком случае. Ваш компонент тогда можно будет настроить, но без настройки он не сломается.
.shady {
font-size: var(--font-size, 12px);
}
Из-за того, что это кастомные свойства, а не просто доллары с автозаменой, они ведут себя как обычные свойства: наследуются вглубь для всех детей элемента и не видны между элементами-соседями. Чтобы переменную точно было видно во всём документе, её нужно задать самому корневому элементу <html>
, но лучше даже :root
, на случай если это корневой элемент <svg>
.
:root {
--font-size: 12px;
--theme-color: tomato;
}
Самое крутое, что переменные можно переопределять внутри медиавыражений. Например, если окно больше каких-то размеров, теперь не нужно копировать весь блок и менять его под новую ширину, достаточно поменять нужные кастомные свойства.
@media (min-width: 320px) {
.shady {
--font-size: 48px;
}
}
Кастомные свойства можно использовать даже внутри функции calc()
, которая посчитает результат выражения внутри. Уже не очень похоже на привычный CSS, правда? Стоит ли говорить, что все препроцессоры уже умерли от зависти, глядя на такое.
.shady {
font-size: calc(var(--font-size) * 2);
}
Ещё кастомные свойства становятся идеальным транспортом для данных между скриптами и стилями. Например, вы можете динамически считать координаты мыши в JS и пробрасывать их в кастомные свойства через setProperty
в нужный элемент.
element.style.setProperty('--pointer-left', event.clientX);
Дальше в стилях уже можно решить: использовать их в top
и left
или transform: translate()
. И наоборот: значение свойства можно получить в JS с помощью getPropertyValue
.
И это я только кастомные свойства лапкой потрогал, дальше ещё куча интересного, что кардинально меняет работу со стилями. Читайте и смотрите дальше сами: статьи, видео и слайды.
Кастомные свойства — это не border-radius
, который либо делает красиво, либо нет. Бросаться всё переделывать на них пока рано, вёрстка может сильно поломаться в браузерах, которые их не поддерживают. Но уже пришло время пробовать и уметь.
Видеоверсия
Вопросы можно задавать здесь.
Zenitchik
И, как обычно, Ишак подкачал...
SelenIT3
Ишак умер (то, что некоторые отдельные, гм… оригиналы отказываются это признавать и закапывать его — другой вопрос). Он больше не поддерживается и не развивается, новых версий не будет. А его наследник, который поддерживается и автоматически обновляется, с октября уже будет поддерживать в полном объеме.
Zenitchik
Т.е. типичное физлицо не станет просматривать сайт с помощью IE? Все перешли на его наследника или другие браузеры?
Это определённо радует.
dom1n1k
IE11 сейчас повторяет роль, которую некогда играл IE6.
Когда все говорили, что его время ушло, что рыночная доля составляет уже единицы процентов, что он вот-вот должен исчезнуть, что пора прекращать поддержку, что ну вот ещё совсем чуть-чуть и тогда уже точно всё!..
И так несколько лет подряд.
Zenitchik
Вот в том и оно… А ещё есть корпоративный сектор, где IE9, зараза, я уж не знаю какую долю процента составляет, а всё никак за горизонт не уйдёт.
SelenIT3
Может быть, всё-таки IE8 (последний доступный на XP)? IE9 мог бы уцелеть на висте и семерке, где автообновление отключили году в 2011-м, но разве эти ОС столько живут без переустановки?
Zenitchik
IE8 — тоже, но меньше.
ОС не живут без прямых рук. А вот без переустановки — запросто. Даже знаменитый глючностью Me.