Os nomes de CSS definidos pelo autor e o DOM de sombra devem funcionar juntos. No entanto, os navegadores são inconsistentes com a especificação, às vezes com cada outro, e cada nome de CSS é inconsistente de uma maneira um pouco diferente.
Este artigo documenta o status atual de como os nomes de CSS definidos pelo autor se comportam em escopos de sombra, com a esperança de que ele possa servir como um guia para melhorar a interoperabilidade em um futuro próximo.
O que são nomes de CSS definidos pelo autor?
Os nomes de CSS definidos pelo autor são um mecanismo de sintaxe de CSS relativamente antigo, originalmente
introduzido para a regra @keyframes, que define um <keyframe-name> como
um identificador personalizado ou uma string. O objetivo desse conceito é declarar
algo em uma parte de uma folha de estilo e fazer referência a ele em outra parte.
/* "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;
}
Outros recursos do CSS que usam nomes do CSS são fontes, declarações de propriedade, consultas de contêiner e, mais recentemente, transições de visualização, posicionamento de âncora e animações movidas por rolagem. A tabela a seguir, que não é abrangente, inclui nomes que o Chrome verifica o estado.
| Recurso | Declaração de nome | Referência de nome | 
|---|---|---|
| Frames-chave | @keyframes | 
      animation-name | 
    
| Fontes | @font-face { }
      @font-palette-values | 
      font-family
      font-palette | 
    
| Declarações de propriedade | @propertyQualquer declaração de propriedade personalizada não registrada  | 
      var() | 
    
| Conferir transições | view-transition-name
      view-transition-class | 
      Pseudoelementos ::view-transition-* | 
    
| Posicionamento da âncora | anchor-name | 
      position-anchor | 
    
| Animação gerada por rolagem | view-timeline-name
      scroll-timeline-name | 
      animation-timeline | 
    
| Estilos de lista | @counter-style | 
      list-style | 
    
| Contadores | counter-reset
      counter-set
      counter-increment | 
    |
| Consultas em contêiner | container-name | 
      @container | 
    
| Página | page | 
      @page | 
    
Como você pode ver na tabela, um nome CSS geralmente tem uma referência CSS correspondente. Por exemplo, animation-name é uma referência ao nome @keyframes. Os nomes CSS são diferentes dos nomes definidos no DOM, como atributos
e nomes de tags, porque são declarados e referenciados no contexto das
folhas de estilo.
Como os nomes se relacionam com o DOM sombra
Enquanto os nomes do CSS são criados para criar relações entre diferentes partes de um documento ou folha de estilo, o DOM sombra é criado para fazer o oposto. Ele encapsula relacionamentos para que eles não vazem em componentes da Web que devem ter o próprio namespace.
Ao combinar nomes CSS e o DOM de sombra, a experiência de composição de componentes da Web precisa ser suficientemente expressiva para ser flexível, mas restrita o suficiente para ser estável.
Isso é bom em teoria. Na prática, os navegadores são inconsistentes na forma como os nomes CSS interagem com o DOM paralelo, tanto entre recursos no mesmo navegador quanto entre navegadores e entre os recursos e a especificação.
Como os nomes e o DOM sombra devem funcionar juntos
Para entender o problema, é importante entender como essas partes do CSS devem funcionar juntas em teoria.
A regra geral
A regra geral sobre como os nomes do CSS se comportam nas árvores de sombra é definida na especificação do nível 1 de escopo do CSS. Resumindo: um nome de CSS é global dentro do escopo em que é definido, ou seja, ele pode ser acessado de árvores shadow descendentes, mas não de árvores shadow irmãs ou ancestral. Isso é diferente dos nomes na plataforma da Web, como IDs de elementos, que são encapsulados no mesmo escopo de árvore.
Exceção à regra: @property
Ao contrário de outros nomes de CSS, as propriedades de CSS não são encapsuladas pelo DOM de sombra.
Em vez disso, elas são o meio comum de transmitir parâmetros em diferentes árvores
de sombra.
Isso torna o
descritor @property
especial: ele precisa se comportar como uma declaração de tipo global do documento que
define como uma propriedade nomeada específica age. Como as propriedades precisam ser correspondentes
em árvores de sombra, a incompatibilidade de declarações de propriedade criaria resultados
inesperados. Portanto, as declarações de @property são especificadas para serem achatadas e resolvidas
de acordo com a ordem do documento.
Como a regra funciona com ::part
As partes de sombra
expõem um elemento dentro de uma árvore de sombra para a árvore mãe. Ao fazer isso, a
árvore pai pode acessar esse elemento e também estilizá-lo usando o elemento
::part.
Como ::part permite que dois escopos de árvore estilizem o mesmo elemento, a seguinte
ordem em cascata é especificada:
- Primeiro, verifique o estilo dentro do contexto da sombra. Esse é o estilo "padrão" da parte.
 - Em seguida, aplique o estilo externo conforme definido em 
::part. Esse é o estilo "personalizado" da peça. - Em seguida, aplique qualquer estilo interno definido com 
!important. Isso permite que um elemento personalizado declare que uma determinada propriedade de uma determinada parte não é personalizável por::part. 
Isso significa que os nomes do DOM shadow não podem ser referenciados por um
::part, já que o ::part é um estilo com escopo de host, e não um estilo com escopo
de shadow. Exemplo:
// 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;  
}
Como a regra funciona com estilos inline
Ao contrário do ::part, os estilos inline com o atributo style ou aqueles
que definem o estilo de forma programática usando o script têm o mesmo escopo do elemento. Isso acontece porque, para aplicar um estilo a um elemento, é necessário ter acesso
ao identificador do elemento e, portanto, à raiz da sombra.
Como os nomes de CSS e o DOM de sombra funcionam juntos na prática
Embora as regras anteriores sejam bem definidas e consistentes, as implementações
atuais nem sempre refletem isso.
Na prática, o @property funciona de maneira diferente da especificação de forma consistente
em todos os navegadores, e a maioria dos outros recursos tem bugs abertos. Alguns deles ainda não
foram lançados, então há tempo para corrigi-los.
Para testar e demonstrar como esses recursos funcionam na prática, criamos a página a seguir: https://css-names-in-the-shadow.glitch.me/. Esta página tem vários iframes, cada um focado em um dos recursos e testando seis cenários:
- Referência externa a um nome externo: sem DOM shadow envolvido, isso deve funcionar.
 - Referência externa a um nome interno: isso não funciona, porque significaria que o nome definido no contexto sombra vazou.
 - Referência interna ao nome externo: isso deve funcionar, já que os nomes no escopo da árvore são herdados pelas raízes de sombra.
 - Referência interna ao nome interno: isso deve funcionar, já que o nome da referência está no mesmo escopo.
 - Referência de 
::partao nome externo: isso deve funcionar, já que o::parte o nome são declarados no mesmo escopo. - Referência 
::partao nome interno: isso não funciona, porque o escopo externo não tem conhecimento sobre os nomes declarados dentro do DOM de sombra. 
@keyframes
Conforme definido na especificação, você pode referenciar nomes de frames-chave
em uma raiz de sombra, desde que a regra @keyframes at-rule esteja em um escopo
ancestral. Na prática, nenhum navegador implementa esse comportamento, e as definições de frame-chave
só podem ser referenciadas no escopo em que são definidas. Consulte
o problema 10540.
@property
Conforme definido na especificação, qualquer declaração de @property será
agrupada no escopo do documento. No entanto, atualmente, em todos os navegadores, só é possível
declarar @property no escopo do documento, e as declarações de @property dentro
de raízes de sombra são ignoradas.
Consulte o problema 10541.
Bugs específicos do navegador
Os outros recursos não mostram um comportamento consistente em todos os navegadores:
@font-faceé achatado para o escopo raiz no Safari.- O Chromium não permite a herança de regras 
anchor-nameem uma raiz sombra scroll-timeline-nameeview-timeline-namenão têm o escopo correto em::part(também no Chromium).- Nenhum navegador permite declarar 
@font-palette-valuesem uma raiz de sombra. view-transition-classpode ser definido dentro de uma raiz sombra (a transição está fora da raiz sombra).- O Firefox permite que 
::partacesse nomes de sombra internos (consultas de contêiner, keyframes). - O Firefox e o Safari não respeitam 
@counter-styleem uma raiz de sombra. 
counter-reset, counter-set e counter-increment têm regras um pouco
diferentes porque são nomes implícitos, e a declaração de propriedades CSS
tem um conjunto de regras estabelecido e bem testado.
Conclusão
A má notícia é que, ao examinar o instantâneo do estado de interoperabilidade atual em relação aos nomes do CSS e ao DOM sombra, a experiência é inconsistente e com bugs. Nenhum dos recursos que examinamos aqui se comporta de maneira consistente em navegadores e de acordo com as especificações. A boa notícia é que o delta para tornar a experiência consistente é uma lista de bugs e problemas de especificação finita. Vamos corrigir isso. Enquanto isso, este resumo pode ajudar se você estiver com dificuldades com as inconsistências descritas neste artigo.