
Web Components und Shadow DOM: Was die Grenze wirklich blockiert
- VersionDude
- guides
- 8 Min. Lesezeit
Das Shadow DOM wird als Kapselung verkauft, was an eine Mauer denken lässt. Es ist genauer: Manches bleibt an der Grenze stehen, anderes überquert sie frei, und zu wissen, was was ist, macht den ganzen Unterschied zwischen einer Komponente, die sich benimmt, und einer, die gegen Ihr Designsystem kämpft.
Das Shadow DOM wird meist mit dem Wort Kapselung eingeführt, und man stellt sich eine Mauer vor. Dieses Bild verursacht die meiste Verwirrung, denn die Grenze ist selektiv und nicht massiv. Manches bleibt an ihr stehen. Anderes geht absichtlich direkt hindurch. Zu lernen, was was ist, ist fast alles, was es zu lernen gibt.
Eine Shadow Root anzuhängen ist eine Zeile in einem Custom Element: this.attachShadow({ mode: 'open' }). Ab dann ist das Markup darin für gewöhnliche Dokumentabfragen nicht mehr erreichbar, und die darin definierten Styles gelten außerhalb nicht mehr. Das ist der Teil, den alle erwarten.
Überraschend ist die andere Richtung. Das globale Stylesheet Ihrer Seite reicht ebenfalls nicht in die Shadow Root hinein. Eine Komponente, die in einer Demo gut aussah, kann in Ihrer Anwendung jede Regel Ihres Designsystems ignorieren, weil diese Regeln an der Grenze genauso fest stehen bleiben, wie die eigenen Styles der Komponente nicht nach außen dringen.
Drei Dinge gehen hindurch, und um sie herum entwirft man. Vererbte CSS-Eigenschaften (font-family, color, line-height und Verwandte) passieren, sofern die Komponente sie nicht zurücksetzt; deshalb sieht eine gut gebaute Komponente meist ohne Aufwand ungefähr richtig aus. Custom Properties gehen ebenfalls hindurch, und zwar absichtlich: Eine Komponente, die --button-bg als Einstiegspunkt anbietet, sagt Ihnen, dass dies der unterstützte Weg ist, sie umzugestalten. Und Events steigen nach außen auf, wobei Composed Events umadressiert werden, sodass der Listener außen das Host-Element sieht statt des internen Knotens, der sie ausgelöst hat.
Diese Umadressierung verdient einen Moment Aufmerksamkeit. Sie ist kein Ärgernis; sie hält die Abstraktion ehrlich. Bekäme Ihr Klick-Handler einen internen Button, den die Autorin der Komponente nächste Woche umbenennt, hingen Sie von einem Implementierungsdetail ab. Die Umadressierung gibt Ihnen stattdessen das öffentliche Objekt.
Die Modi open und closed sind weniger symmetrisch, als sie aussehen. Open heißt, dass element.shadowRoot die Root zurückgibt, also kann jeder von außen hinein. Closed gibt null zurück, was nach Sicherheitsgrenze klingt und keine ist: Der Code der Komponente behält die Referenz, und alles, was in der Seite läuft, kommt auf anderen Wegen heran. Der Modus closed erschwert Kopplung; er erzwingt keine Privatheit. Wählen Sie ihn, um eine Absicht mitzuteilen, nie um etwas zu schützen.
Slots sind der Weg, Inhalte hereinzulassen, ohne die Struktur aufzugeben. Ein <slot>-Element in der Shadow Root markiert eine Stelle, an der Markup aus dem Light DOM angezeigt wird: Der Inhalt gehört weiter der Seite, wird vom Stylesheet der Seite gestaltet und lediglich im Layout der Komponente dargestellt. Das macht Web Components zusammensetzbar statt undurchsichtig, und genau hier wirken die Styling-Regeln am seltsamsten: Inhalt in einem Slot wird von außen gestaltet, abgesehen von den begrenzten Anpassungen, die die Komponente mit ::slotted() vornehmen kann.
Für Styling von außen ist die moderne Schnittstelle ::part(). Die Autorin einer Komponente markiert ein internes Element mit part="label", und die Seite kann dann ::part(label) gestalten, ohne sonst etwas über das Innere zu wissen. Das ist ein bewusster, versionierbarer Vertrag, das Gegenteil eines Nachfahren-Selektors, der hineingreift und hofft, dass sich die Struktur nie ändert.
Ehrlich zusammengefasst tauscht das Shadow DOM Bequemlichkeit gegen Stabilität. Sie verzichten darauf, alles von überall umgestalten zu können, und erhalten Komponenten, die weiter funktionieren, wenn sich die Seite um sie herum ändert. In einer kleinen Anwendung eines einzigen Teams lohnt sich dieser Tausch oft nicht. In einer Komponentenbibliothek, die von Teams genutzt wird, die Sie nie treffen werden, ist er genau der Sinn der Sache.
FAQ
Warum gilt mein globales CSS nicht in einer Web Component?
Weil die Shadow-Grenze Styles in beide Richtungen blockiert. Das Stylesheet Ihrer Seite endet an der Shadow Root genauso, wie die internen Styles der Komponente dort auf dem Weg nach außen enden. Das ist gewollt: So sieht eine Komponente überall gleich aus, wo sie eingesetzt wird. Um sie von außen zu gestalten, nutzen Sie die Einstiegspunkte, die sie anbietet, Custom Properties oder ::part()-Selektoren, statt hineinzugreifen.
Was ist der Unterschied zwischen offener und geschlossener Shadow Root?
Mit mode 'open' gibt element.shadowRoot die Root zurück, und Code von außen kann sie durchlaufen. Mit 'closed' gibt diese Eigenschaft null zurück. Wichtig ist: closed ist keine Sicherheitsfunktion. Der eigene Code der Komponente behält eine Referenz, und Seitenskripte haben andere Wege hinein. Der Modus closed teilt mit, dass das Innere keine unterstützte API ist; er schützt es nicht.
Verlassen Events das Shadow DOM?
Composed Events ja, und sie werden beim Überqueren der Grenze umadressiert: Ein Listener außen sieht das Host-Custom-Element als Ziel statt des internen Elements, das das Event ausgelöst hat. Das ist Absicht: Ihr Handler hängt von der öffentlichen Identität der Komponente ab statt von ihrer internen Struktur, die sich ohne Vorwarnung ändern kann.
Wie lasse ich Seiteninhalt in eine Komponente?
Mit Slots. Ein <slot>-Element in der Shadow Root markiert, wo Inhalt aus dem Light DOM dargestellt wird. Dieser Inhalt gehört weiter der Seite und wird von ihr gestaltet, was meist gewünscht ist: Die Komponente steuert das Layout, die Seite die Worte. Die Komponente kann mit ::slotted() begrenzte Anpassungen vornehmen, übernimmt den Inhalt aber nicht.
Brauche ich das Shadow DOM wirklich?
Nicht immer. Es erkauft Isolation mit Bequemlichkeit, und in einer einzelnen Anwendung eines Teams löst die Isolation womöglich ein Problem, das Sie nicht haben. Klar lohnend wird es, wenn Ihre Komponente in Seiten eingesetzt wird, die Sie nicht kontrollieren, von Menschen, die nicht wissen sollten, wie sie gebaut ist.


