Типизированные CSS переменные с @property

—

от автора

Эта статья — перевод оригинальной статьи «Type safe CSS design systems with @property«.

Также я веду телеграм канал “Frontend по-флотски”, где рассказываю про интересные вещи из мира разработки интерфейсов.

Вступление

Типы CSS — это достойное вложение в безопасность типов при работе с внешним интерфейсом. Мы все еще ожидаем кроссбраузерности, но мы к этому придем ? .

Если вы никогда не видели типизированную CSS-переменную с @property, то вот пример:

@property --focal-size {   syntax: '<length-percentage>';   initial-value: 100%;   inherits: false; }

Я использовал её, чтобы анимировать изображение с градиентной маской. Довольно мило.

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

Основы безопасности CSS типов

При изучении Rust или TypeScript лучше всего начать с примитивов типов. В CSS их несколько:

Больше типов на MDN и полный список грамматик и типов на csswg.org/indexes/#types.

Еще одно определение переменной:

@property --hue {   syntax: '<angle>';   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 значение <color>, а не <angle>. Но я думаю, что более качественный инструментарий мог бы помочь ?.

Уровень 2

Пока что я создал переменную как <angle> и использовал её в свойстве background. Никакой вложенности свойств.

Перейдем на более глубокий уровень, сделав переменную использующую другую переменную. Здесь --_bg — это <any> (потому что на данный момент это не типизированная переменная), с вложенной переменной --hue:

.card {   --_bg: oklch(98% .01 var(--hue));   background: var(--_bg);    @media (prefers-color-scheme: dark) {     --_bg: oklch(15% .1 var(--hue));   } }

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

Актуальность систем проектирования

Давайте сделаем типизированный стартер адаптивной цветовой схемы для светлых и темных тем!

Во-первых, безопасный для типа значение hue. Я сделаю элемент <input type=text>, который будет записывать в это значение все, что мы в него введем. Поскольку он безопасен для типов, мы увидим, как другие пользовательские свойства, зависящие от него, не сломаются, если значение параметра --hue будет установлено в «poots» или что-то в этом роде.

@property --hue {   syntax: '<angle>';   initial-value: 5rad;   inherits: true; }

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

Вот 3 слоя, один из которых будет фоном страницы —surface, и два других, которые будут либо поверх bg страницы, либо под ним. Их начальное значение не вызывает восторга, но мы дойдем до этого в следующей части.

@property --surface {   syntax: '<color>';   initial-value: #333;   inherits: true; }  @property --surface-over {   syntax: '<color>';   initial-value: #444;   inherits: true; }  @property --surface-under {   syntax: '<color>';   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.

Системы проектирования скоро станут намного умнее и стабильнее.


ссылка на оригинал статьи https://habr.com/ru/articles/759818/