@property: наделение CSS-переменных сверхспособностями

CSS Houdini — это общий термин, который охватывает набор низкоуровневых API-интерфейсов раскрывающих части механизма рендеринга CSS и предоставляющих разработчикам доступ к объектной модели CSS. Это огромное изменение для экосистемы CSS, потому что оно позволяет разработчикам указывать браузеру, как читать и анализировать пользовательский CSS, не дожидаясь, пока поставщики браузеров предоставят встроенную поддержку этих функций.

Одним из самых интересных дополнений к CSS в рамках Houdini является API свойств и значений. Этот API-интерфейс расширяет пользовательские CSS-свойства (обычно называемые CSS-переменными), придавая им семантическое значение (определяемое синтаксисом) и даже резервные значения, позволяя тестировать CSS.

Написание пользовательских Houdini-свойств

Вот пример установки настраиваемого свойства (можно считать: CSS-переменной), но теперь у него есть поля: syntax (c типом), initial-value (с начальным значением) и inherits (наследует ли оно значение от своего родителя). То же самое можно сделать с помощью JavaScript — CSS.registerProperty(), но в Chromium 85 и более поздних версиях синтаксис @property поддерживает уже в CSS:

В JavaScript (Chromium 78)

CSS.registerProperty({
  name: '--colorPrimary',
  syntax: '<color>',
  initialValue: 'magenta',
  inherits: false
});

В CSS (Chromium 85)

@property --colorPrimary {
  syntax: '<color>';
  initial-value: magenta;
  inherits: false;
}

Теперь вы можете получить доступ к --colorPrimary, как и к любому другому настраиваемому CSS-свойству, через var(-- colorPrimary). Однако разница в том, что --colorPrimary теперь не просто строка. У него есть данные.

Важно: при написании зарегистрированного настраиваемого свойства с указанным syntax требуется указать initial-value (начальное значение).

Резервные значения

Как для любого другого настраиваемого свойства, здесь можно получать (используя var) или устанавливать (записывать/перезаписывать) значения. Но с настраиваемыми Houdini-свойствами, если при переопределении установить неожиданное для него значение, механизм визуализации CSS вместо игнорирования строки отправит предустановленное начальное значение.

Рассмотрим пример ниже. Начальное значение initial-value для переменной --colorPrimary установлено magenta. Затем разработчик присвоил ему недопустимое для цвета значение 23. Без @property CSS-парсер проигнорирует недопустимую пару свойство-значение. С @property синтаксический анализатор в этом случае вернёт начальное значение magenta.

.card {
  background-color: var(--colorPrimary); /* magenta */
}

.highlight-card {
  --colorPrimary: yellow;
  background-color: var(--colorPrimary); /* yellow */
}

.another-card {
  --colorPrimary: 23;
  background-color: var(--colorPrimary); /* magenta */
}

Syntax

Используя syntax теперь можно писать семантический CSS с указанием типа. К текущим разрешенным типам относятся:

  • length
  • number
  • percentage
  • length-percentage
  • color
  • image
  • url
  • integer
  • angle
  • time
  • resolution
  • transform-list
  • transform-function
  • custom-ident (строка настраиваемого идентификатора)

Установка syntax позволяет браузеру проверять тип настраиваемых свойств (CSS-переменных). Это дает много преимуществ.

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

При использовании настраиваемого свойства с syntax: '<number>', градиент слева показывает плавный переход между конечными значениями. Градиент справа использует настраиваемое свойство по умолчанию (syntax не определен) и показывает резкий переход.

В этом примере при наведении курсора точки установки градиента анимируются от начального значения 40% до конечного значения 100%. Предполагается, что пользователь должен увидеть плавное изменение перехода цвета вертикального градиента сверху вниз.

Браузер слева поддерживает API Houdini- свойств и значений. Это обеспечивает плавный переход с установкой градиента. В браузере справа нет такой поддержки и он может воспринимать это только как изменение значения строки с одного сразу на другое. Невозможность интерполировать значения приводит к отсутствию эффектного плавного перехода.

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

/* Проверка поддержки Houdini и регистрация свойства */
@supports (background: paint(houdini)) {
  @property --gradPoint {
    syntax: '<percentage>';
    inherits: false;
    initial-value: 40%;
  }
}

А когда придет время его анимировать, можно обновить значение с начальных 40% до 100%:

@supports (background: paint(houdini)) {
  .post:hover,
  .post:focus {
    --gradPoint: 100%;
  }
}

Теперь это поможет реализовать для градиента плавный переход.

Плавная анимация градиентной рамки
Плавная анимация градиентной рамки.

See this code Demo of Houdini @property on x.xhtml.ru.

Заключение

Правило @property делает захватывающую технологию ещё доступнее, позволяя писать семантически значимый CSS внутри самого CSS. Чтобы узнать больше о Houdini-CSS и API Houdini- свойств и значений, ознакомьтесь с этими ресурсами: