Door de auteur gedefinieerde CSS-namen en de schaduw-DOM zouden moeten samenwerken. Browsers zijn echter inconsistent met de specificatie, soms met elkaar, en elke CSS-naam is op een iets andere manier inconsistent.
Dit artikel documenteert de huidige status van hoe door de auteur gedefinieerde CSS-namen zich gedragen in schaduwbereiken, in de hoop dat dit als leidraad kan dienen om de interoperabiliteit in de nabije toekomst te verbeteren.
Wat zijn door de auteur gedefinieerde CSS-namen?
Door de auteur gedefinieerde CSS-namen zijn een relatief oud CSS-syntaxismechanisme, oorspronkelijk geïntroduceerd voor de @keyframes
-regel, die een <keyframe-name>
definieert als een aangepaste ident of een tekenreeks. Het doel van dit concept is om iets in een deel van een stylesheet te declareren en ernaar te verwijzen in een ander deel.
/* "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;
}
Andere CSS-functies die CSS-namen gebruiken zijn lettertypen, eigenschapsdeclaraties, containerquery's en, meer recentelijk, weergaveovergangen, ankerpositionering en scrollgestuurde animaties. De volgende niet-uitgebreide tabel bevat namen waarvan Chrome de status controleert.
Functie | Naamverklaring | Naamreferentie |
---|---|---|
Sleutelframes | @keyframes | animation-name |
Lettertypen | @font-face { } @font-palette-values | font-family font-palette |
Eigendomsverklaringen | @property Elke niet-geregistreerde aangepaste eigendomsverklaring | var() |
Overgangen bekijken | view-transition-name view-transition-class | ::view-transition-* pseudo-elementen |
Anker positionering | anchor-name | position-anchor |
Scrollgestuurde animatie | view-timeline-name scroll-timeline-name | animation-timeline |
Lijststijlen | @counter-style | list-style |
Tellers | counter-reset counter-set counter-increment | |
Containerquery's | container-name | @container |
Pagina | page | @page |
Zoals je in de tabel kunt zien, heeft een CSS- naam meestal een overeenkomstige CSS- referentie . animation-name
is bijvoorbeeld een verwijzing naar de naam @keyframes
. CSS-namen verschillen van namen die in de DOM zijn gedefinieerd, zoals attributen en tagnamen, omdat ze worden gedeclareerd en er vervolgens naar wordt verwezen binnen de context van stylesheets.
Hoe namen zich verhouden tot de schaduw-DOM
Terwijl CSS-namen zijn gebouwd om relaties tussen verschillende delen van een document of stylesheet te creëren, is Shadow DOM gebouwd om het tegenovergestelde te doen. Het kapselt relaties in, zodat ze niet lekken via webcomponenten die hun eigen naamruimte zouden moeten hebben.
Door CSS-namen en de schaduw-DOM samen te brengen, moet de ervaring van het samenstellen van webcomponenten expressief genoeg aanvoelen om flexibel te zijn, maar ook beperkt genoeg om stabiel te zijn.
Dit is in theorie goed. In de praktijk zijn browsers inconsistent in de manier waarop CSS-namen samenwerken met de schaduw-DOM, zowel tussen functies in dezelfde browser, tussen browsers, als tussen de functies en de specificatie.
Hoe namen en de schaduw-DOM moeten samenwerken
Om het probleem te begrijpen, is het de moeite waard om te begrijpen hoe deze delen van CSS in theorie zouden moeten samenwerken.
De algemene regel
De algemene regel voor hoe CSS-namen zich gedragen in schaduwbomen is gedefinieerd in de CSS Scoping Level 1-specificatie . Samenvattend: een CSS-naam is globaal binnen het bereik waarin deze is gedefinieerd, wat betekent dat deze toegankelijk is via schaduwbomen van afstammelingen, maar niet van schaduwbomen van broers en zussen of voorouders. Merk op dat dit anders is dan namen op het webplatform, zoals element-ID's, die binnen hetzelfde boombereik zijn ingekapseld.
Uitzondering op de regel: @property
In tegenstelling tot andere CSS-namen worden CSS-eigenschappen niet ingekapseld door schaduw-DOM. Integendeel, ze zijn de gebruikelijke manier om parameters door te geven aan verschillende schaduwbomen. Dit maakt de @property
descriptor speciaal: deze zou zich moeten gedragen als een document-globale typedeclaratie die definieert hoe een bepaalde benoemde eigenschap zich gedraagt. Omdat eigenschappen over schaduwbomen heen moeten overeenkomen, zou een niet-overeenkomende eigenschapsdeclaratie tot onverwachte resultaten leiden. Daarom worden @property
declaraties gespecificeerd om te worden afgevlakt en opgelost volgens de documentvolgorde.
Hoe de regel zou moeten werken met ::part
Schaduwdelen stellen een element binnen een schaduwboom bloot aan de bovenliggende boom. Door dit te doen kan de bovenliggende boom toegang krijgen tot dat element en het ook opmaken met behulp van het ::part
element.
Omdat ::part
toestaat dat twee boomscopes hetzelfde element opmaken, wordt de volgende cascadevolgorde gespecificeerd:
- Controleer eerst de stijl binnen de schaduwcontext. Dit is de "standaard" stijl van het onderdeel.
- Pas vervolgens de externe stijl toe zoals gedefinieerd in
::part
. Dit is de "aangepaste" stijl van het onderdeel. - Pas vervolgens elke interne stijl toe die samen met
!important
is gedefinieerd. Hierdoor kan een aangepast element verklaren dat een bepaalde eigenschap van een bepaald onderdeel niet kan worden aangepast door::part
.
Dit betekent dat er niet naar namen vanuit de schaduw-DOM kan worden verwezen vanuit een ::part
, omdat de ::part
een host-scoped stijl is in plaats van een schaduw-scoped stijl. Bijvoorbeeld:
// 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;
}
Hoe de regel zou moeten werken met inline stijlen
In tegenstelling tot ::part
zijn inline stijlen met het style
attribuut, of stijlen die de stijl programmatisch instellen met behulp van script, van toepassing op het bereik van het element. Dat komt omdat je, om een stijl op een element toe te passen, toegang nodig hebt tot de elementhandle, en dus tot de schaduwwortel zelf.
Hoe CSS-namen en de schaduw-DOM in werkelijkheid samenwerken
Hoewel de voorgaande regels goed gedefinieerd en consistent zijn, weerspiegelen de huidige implementaties dat niet altijd. In de praktijk werkt @property
op een consistente manier in alle browsers anders dan de specificaties, en de meeste andere functies bevatten openstaande bugs (sommige ervan zijn nog niet vrijgegeven, dus er is tijd om ze te repareren).
Om te testen en te demonstreren hoe deze functies in de praktijk werken, hebben we de volgende pagina gemaakt: https://css-names-in-the-shadow.glitch.me/ . Deze pagina bevat verschillende iframes, elk gericht op een van de functies en het testen van zes scenario's:
- Externe verwijzing naar een externe naam : er is geen schaduw-DOM bij betrokken, dit zou moeten werken.
- Uiterlijke verwijzing naar een innerlijke naam : dit zou niet moeten werken, omdat dat zou betekenen dat de naam die in de schaduwcontext is gedefinieerd, is gelekt.
- Innerlijke verwijzing naar uiterlijke naam : dit zou moeten werken, omdat namen met een boombereik worden overgenomen door schaduwwortels.
- Innerlijke verwijzing naar innerlijke naam : dit zou moeten werken, omdat beide namen van de verwijzing zich in hetzelfde bereik bevinden.
-
::part
verwijzing naar buitenste naam : dit zou moeten werken, omdat zowel het::part
als de naam in dezelfde scope worden gedeclareerd. -
::part
verwijzing naar innerlijke naam : dit zou niet moeten werken, omdat de buitenste scope geen kennis zou moeten verwerven over namen die binnen de schaduw-DOM zijn gedeclareerd.
@keyframes
Zoals gedefinieerd in de specificatie, zou u moeten kunnen verwijzen naar sleutelframenamen vanuit een schaduwwortel, zolang de at-regel @keyframes
zich in een bovenliggend bereik bevindt. In de praktijk implementeert geen enkele browser dit gedrag, en er kan alleen naar de sleutelframedefinities worden verwezen in het bereik waarin ze zijn gedefinieerd. Zie uitgave 10540 .
@property
Zoals gedefinieerd in de specificatie, wordt elke declaratie van @property
afgevlakt naar het documentbereik. Tegenwoordig kunt u echter in alle browsers alleen @property
declareren in het documentbereik en worden @property
declaraties binnen schaduwwortels genegeerd.
Zie uitgave 10541 .
Browserspecifieke bugs
De andere functies vertonen geen consistent gedrag in alle browsers:
-
@font-face
is afgevlakt tot het hoofdbereik in Safari. - Chromium staat het overnemen van
anchor-name
in een schaduwroot niet toe -
scroll-timeline-name
enview-timeline-name
hebben niet de juiste scope op::part
(ook in Chromium). - Geen enkele browser staat het declareren
@font-palette-values
in een schaduwwortel toe. -
view-transition-class
kan binnen een schaduwwortel worden gedefinieerd (de overgang zelf bevindt zich buiten de schaduwwortel). - Firefox geeft
::part
toegang tot innerlijke schaduwnamen (containerquery's, sleutelframes). - Firefox en Safari respecteren
@counter-style
in een schaduwroot niet.
Houd er rekening mee dat counter-reset
, counter-set
, counter-increment
enigszins verschillende regels hebben omdat het impliciete namen zijn, en dat het declareren van CSS-eigenschappen een gevestigde en goed geteste set regels heeft.
Conclusie
Het slechte nieuws is dat bij het onderzoeken van de momentopname van de huidige interoperabiliteitsstatus met betrekking tot CSS-namen en de schaduw-DOM de ervaring inconsistent en met fouten is. Geen van de functies die we hier hebben onderzocht, gedraagt zich consistent in alle browsers en volgens de specificaties. Het goede nieuws is dat de delta om de ervaring consistent te maken een eindige lijst van bugs en spec-problemen is. Laten we dit oplossen! In de tussentijd kan dit overzicht je hopelijk helpen als je worstelt met de inconsistenties die in dit artikel worden beschreven.