Типизированные CSS переменные с @property / Хабр
Эта статья — перевод оригинальной статьи “Type safe CSS design systems with @property”.
Также я веду телеграм канал “Frontend по-флотски”, где рассказываю про интересные вещи из мира разработки интерфейсов.
Вступление
Типы CSS – это достойное вложение в безопасность типов при работе с внешним интерфейсом. Мы все еще ожидаем кроссбраузерности, но мы к этому придем 🙂 .
Если вы никогда не видели типизированную CSS-переменную с @property, то вот пример:
@property –focal-size {
syntax: ‘
initial-value: 100%;
inherits: false;
}
Я использовал её, чтобы анимировать изображение с градиентной маской. Довольно мило.
Вот предварительный обзор того, что может сделать безопасность типов CSS, и того, что я буду объяснять:
Основы безопасности CSS типов
При изучении Rust или TypeScript лучше всего начать с примитивов типов. В CSS их несколько:
Больше типов на MDN и полный список грамматик и типов на csswg.org/indexes/#types.
Еще одно определение переменной:
@property –hue {
syntax: ‘
initial-value: .5turn;
inherits: false;
}
Используйте её так же, как и var(–hue), и она будет равна .5turn. Но попробуйте установить его в значение, не соответствующее её типу? Не получится, значение по-прежнему будет равно .5turn. Переменная не позволит присвоить себе значение, не соответствующее её типу, всегда возвращаясь к последнему подходящему значению.
.card {
–hue: 90deg; /* ✅ */
–hue: #f00; /* ❌ */
background: oklch(98% .01 var(–hue));
/* background will always resolve 👍🏻 */
/* –hue resolves 90deg *.
}
Это безопасность CSS типов. Она не приводит к краху страницы, не блокирует поток и, к сожалению, не сообщает в консоли о том, что была попытка установить для свойства –hue значение
Уровень 2
Пока что я создал переменную как
Перейдем на более глубокий уровень, сделав переменную использующую другую переменную. Здесь –_bg – это
.card {
–_bg: oklch(98% .01 var(–hue));
background: var(–_bg);
@media (prefers-color-scheme: dark) {
–_bg: oklch(15% .1 var(–hue));
}
}
Вы можете углубиться на много уровней, но не бесконечно. И можно типизировать некоторые или все переменные. Далее мы создадим несколько типизированных переменных с двухуровневой глубиной.
Актуальность систем проектирования
Давайте сделаем типизированный стартер адаптивной цветовой схемы для светлых и темных тем!
Во-первых, безопасный для типа значение hue. Я сделаю элемент , который будет записывать в это значение все, что мы в него введем. Поскольку он безопасен для типов, мы увидим, как другие пользовательские свойства, зависящие от него, не сломаются, если значение параметра –hue будет установлено в “poots” или что-то в этом роде.
@property –hue {
syntax: ‘
initial-value: 5rad;
inherits: true;
}
Для краткости я буду задавать только поверхностные слои адаптивной цветовой схемы, но это даст понимание процесса создания системы дизайна.
Вот 3 слоя, один из которых будет фоном страницы –surface, и два других, которые будут либо поверх bg страницы, либо под ним. Их начальное значение не вызывает восторга, но мы дойдем до этого в следующей части.
@property –surface {
syntax: ‘
initial-value: #333;
inherits: true;
}
@property –surface-over {
syntax: ‘
initial-value: #444;
inherits: true;
}
@property –surface-under {
syntax: ‘
initial-value: #222;
inherits: true;
}
Важным здесь является то, что они относятся к цветовому типу.
Теперь мы можем присвоить цветам слоёв более понятные значения. При желании можно использовать @media (prefers-color-scheme), но здесь, поскольку я хотел показать светлое и темное с помощью переключателя, я использую :has():
@layer demo.theme {
html:has(#light:checked) {
color-scheme: light;
–surface: oklch(90% .05 var(–hue));
–surface-over: oklch(99% .02 var(–hue));
–surface-under: oklch(85% .075 var(–hue));
}
html:has(#dark:checked) {
color-scheme: dark;
–surface: oklch(20% .1 var(–hue));
–surface-over: oklch(30% .1 var(–hue));
–surface-under: oklch(15% .1 var(–hue));
}
}
Вот, собственно, и вся настройка и оркестровка типизированных переменных. Остается только использовать их. Загляните в Codepen, чтобы увидеть все возможные способы их использования для создания адаптивной цветовой схемы: тени, фона и многое другое!
CodePen
Последняя часть
Попробуйте вводить всякую ерунду, в текстовое поле “Theme tint” в CodePen демо-версии. Ни одна из цветовых систем не даст сбоя из-за опечатки или присвоенного значения, не соответствующего типу. Браузер точно знает, как сделать обратный ход и обработать ошибки.
На @property можно построить очень надежную и большую систему. Те же типы безопасности типов при разработке, что и в Typescript, но типы действительно передаются браузеру и соблюдаются. Rad.
Firefox уже почти закончил свою реализацию, что сделает @property кроссбраузерно стабильной 🎉.
Информацию о поддержке можно узнать на сайте caniuse.
Системы проектирования скоро станут намного умнее и стабильнее.