Определенные автором имена CSS и теневой DOM должны работать вместе. Однако браузеры несовместимы со спецификацией, иногда друг с другом, и каждое имя CSS несовместимо по-своему.
В этой статье документируется текущий статус того, как определенные автором имена CSS ведут себя в теневых областях, с надеждой, что она может послужить руководством для улучшения совместимости в ближайшем будущем.
Что такое имена CSS, определенные автором?
 Определенные автором имена CSS — это относительно старый синтаксический механизм CSS, первоначально представленный для правила @keyframes , которое определяет <keyframe-name> либо как пользовательский идентификатор, либо как строку. Цель этой концепции — объявить что-то в одной части таблицы стилей и ссылаться на это в другой части.
/* "fade-in" is a CSS name, representing a set of keyframes */
@keyframes fade-in {
  from { opacity: 0 };
  to { opacity: 1 }
}
.card {
  /* "fade-in" is a reference to the above keyframes */
  animation-name: fade-in;
}
Другие функции CSS, использующие имена CSS, — это шрифты, объявления свойств, запросы контейнеров, а в последнее время — переходы представлений, позиционирование привязки и анимация, управляемая прокруткой. В следующей неполной таблице приведены имена, состояние которых Chrome проверяет.
| Особенность | Объявление имени | Ссылка на имя | 
|---|---|---|
| Ключевые кадры |  @keyframes |  animation-name | 
| Шрифты |  @font-face { }@font-palette-values |  font-familyfont-palette | 
| Декларации о собственности |  @propertyЛюбая незарегистрированная декларация пользовательских свойств  |  var() | 
| Просмотр переходов |  view-transition-nameview-transition-class |  ::view-transition-* псевдоэлементы | 
| Расположение якоря |  anchor-name |  position-anchor | 
| Анимация, управляемая прокруткой |  view-timeline-namescroll-timeline-name |  animation-timeline | 
| Список стилей |  @counter-style |  list-style | 
| Счетчики |  counter-resetcounter-setcounter-increment | |
| Контейнерные запросы |  container-name |  @container | 
| Страница |  page |  @page | 
 Как видно из таблицы, имя CSS обычно имеет соответствующую ссылку CSS. Например, animation-name — это ссылка на имя @keyframes . Имена CSS отличаются от имен, определенных в DOM, таких как имена атрибутов и тегов, поскольку они объявляются, а затем на них ссылаются в контексте таблиц стилей.
Как имена связаны с теневым DOM
В то время как имена CSS созданы для создания связей между различными частями документа или таблицы стилей, Shadow DOM создан для обратного. Он инкапсулирует отношения, поэтому они не передаются через веб-компоненты, которые должны иметь собственное пространство имен.
Объединив имена CSS и теневой DOM, процесс создания веб-компонентов должен быть достаточно выразительным, чтобы быть гибким, но достаточно ограниченным, чтобы быть стабильным.
Это хорошо в теории. На практике браузеры несовместимы в том, как имена CSS взаимодействуют с теневым DOM, как между функциями в одном браузере, между браузерами, так и между функциями и спецификациями.
Как имена и теневой DOM должны работать вместе
Чтобы понять проблему, стоит понять, как эти части CSS теоретически должны работать вместе.
Общее правило
Общее правило поведения CSS-имен в теневых деревьях определено в спецификации CSS Scoping Level 1 . Подводя итог: имя CSS является глобальным внутри области, в которой оно определено, то есть к нему можно получить доступ из теневых деревьев-потомков, но не из родственных или родительских теневых деревьев. Обратите внимание, что это отличается от имен на веб-платформе, таких как идентификаторы элементов, которые инкапсулированы в той же области дерева.
 Исключение из правила: @property
 В отличие от других имен CSS, свойства CSS не инкапсулируются теневым DOM. Скорее, они являются общим средством передачи параметров между разными теневыми деревьями. Это делает дескриптор @property особенным: он должен вести себя как объявление глобального типа документа, определяющее, как действует конкретное именованное свойство. Поскольку свойства должны совпадать во всех теневых деревьях, несоответствие объявлений свойств может привести к неожиданным результатам, поэтому объявления @property указываются так, чтобы их можно было сгладить и разрешить в соответствии с порядком документа.
 Как правило должно работать с ::part
 Теневые части предоставляют элемент внутри теневого дерева его родительскому дереву. Таким образом, родительское дерево сможет получить доступ к этому элементу, а также стилизовать его с помощью элемента ::part .
 Поскольку ::part позволяет двум областям дерева стилизовать один и тот же элемент, указан следующий каскадный порядок:
- Сначала проверьте стиль внутри теневого контекста. Это стиль детали «по умолчанию».
 -  Затем примените внешний стиль, как определено в 
::part. Это «индивидуальный» стиль детали. -  Затем примените любой внутренний стиль, определенный вместе с 
!important. Это позволяет пользовательскому элементу объявить, что определенное свойство определенной части не может быть изменено с помощью::part. 
 Это означает, что имена из теневого DOM не могут ссылаться на ::part , поскольку ::part является стилем области хоста, а не стилем теневой области. Например:
// inside the shadow DOM:
@keyframes fade-in {
  from { opacity: 0}
}
// This shouldn't work!
// The host style shouldn't know the name "fade-in"
::part(slider) {
  animation-name: fade-in;  
}
Как правило должно работать со встроенными стилями
 В отличие от ::part , встроенные стили с атрибутом style или стили, которые программно задают стиль с помощью скрипта, ограничены областью действия элемента. Это связано с тем, что для применения стиля к элементу вам необходим доступ к дескриптору элемента и, следовательно, к самому теневому корню. 
Как имена CSS и теневой DOM работают вместе в реальности
 Хотя предыдущие правила четко определены и последовательны, текущие реализации не всегда это отражают. На практике @property работает не так, как указано в спецификации, и единообразно во всех браузерах, а в большинстве других функций есть открытые ошибки (некоторые из них еще не выпущены, поэтому есть время их исправить).
Чтобы протестировать и продемонстрировать, как эти функции работают на практике, мы создали следующую страницу: https://css-names-in-the-shadow.glitch.me/ . На этой странице есть несколько iframe, каждый из которых ориентирован на одну из функций и тестирует шесть сценариев:
- Внешняя ссылка на внешнее имя : теневой DOM не используется, это должно работать.
 - Внешняя ссылка на внутреннее имя : это не должно работать, так как это будет означать, что имя, определенное в теневом контексте, просочилось.
 - Внутренняя ссылка на внешнее имя : это должно работать, поскольку имена в области дерева наследуются теневыми корнями.
 - Внутренняя ссылка на внутреннее имя : это должно работать, поскольку оба имени ссылки находятся в одной области.
 -  Ссылка 
::partна внешнее имя : это должно работать, поскольку и::part, и имя объявлены в одной области. -  
::partссылка на внутреннее имя : это не должно работать, поскольку внешняя область не должна получать сведения об именах, объявленных внутри теневого DOM. 
 @keyframes
 Как определено в спецификации, вы должны иметь возможность ссылаться на имена ключевых кадров из теневого корня, если at-правило @keyframes находится в области предка. На практике ни один браузер не реализует такое поведение, и на определения ключевых кадров можно ссылаться только в той области, в которой они определены. См . выпуск 10540 .
 @property
 Как определено в спецификации, любое объявление @property будет сведено к области документа. Однако сегодня во всех браузерах вы можете объявлять @property только в области документа, а объявления @property в теневых корнях игнорируются.
 См . выпуск 10541 .
Специфические ошибки браузера
Другие функции не демонстрируют единообразного поведения в разных браузерах:
-  
@font-faceсводится к корневой области Safari. -  Chromium не позволяет наследовать правила 
anchor-nameв теневом корне -  
scroll-timeline-nameи имяview-timeline-nameне имеют правильной области видимости в::part(также в Chromium). -  Ни один браузер не позволяет объявлять 
@font-palette-valuesв теневых корнях. -  
view-transition-classможет быть определен внутри теневого корня (сам переход находится вне теневого корня). -  Firefox позволяет 
::partполучать доступ к внутренним теневым именам (запросы контейнера, ключевые кадры). -  Firefox и Safari не учитывают 
@counter-styleв теневом корне. 
 Обратите внимание, что counter-reset , counter-set , counter-increment имеют немного разные правила, поскольку они являются неявными именами, а объявление свойств CSS имеет установленный и хорошо проверенный набор правил.
Заключение
Плохая новость заключается в том, что при проверке снимка текущего состояния взаимодействия с учетом имен CSS и теневого DOM результат оказывается непоследовательным и ошибочным. Ни одна из рассмотренных здесь функций не работает одинаково в разных браузерах и не соответствует спецификациям. Хорошей новостью является то, что дельта, обеспечивающая единообразие опыта, — это ограниченный список ошибок и проблем со спецификациями. Давайте это исправим! Тем временем, мы надеемся, что этот обзор может помочь, если вы боретесь с несоответствиями, описанными в этой статье.