Nolan Lawson hat ein kleines emoji-picker-element, das ist außerordentlich praktisch und unglaublich einfach zu bedienen. Aber da Sie es wahrscheinlich innerhalb Ihrer eigenen Anwendung verwenden würden, sollte es gestaltbar sein, damit es sich überall gut einfügen lässt. Wie man das ermöglicht, ist nicht gerade offensichtlich
Was mir jedoch nicht klar war, war, wie man es Benutzern ermöglichen kann, es zu gestalten. Was, wenn sie eine andere Hintergrundfarbe wünschen? Was, wenn sie möchten, dass die Emojis größer sind? Was, wenn sie eine andere Schriftart für das Eingabefeld wünschen?
Nolan listet vier Möglichkeiten auf (ich werde sie ein wenig umbenennen, um sie besser zu verstehen).
- CSS Custom Properties: Gestalten Sie Dinge wie
background: var(--background, white);. Custom Properties durchdringen den Shadow DOM, sodass Sie im Wesentlichen Styling-Hooks hinzufügen. - Vorgefertigte Varianten: Sie können dem benutzerdefinierten Element ein
class-Attribut hinzufügen, das dank der Pseudo-Selektoren innerhalb des CSS im Shadow DOM leicht zugänglich ist, wie:host(.dark) { background: black; }. - Shadow-Teile: Sie fügen Attribute zu Dingen hinzu, die gestaltbar sein sollen, wie
<span part="foo">, dann kann CSS von außen übercustom-component::part(foo) { }darauf zugreifen. - Benutzererzwungen: Trotz der Nichts-rein-Nichts-raus-Philosophie des Shadow DOM können Sie immer auf
element.shadowRootzugreifen und ein<style>einfügen, so dass es immer eine Möglichkeit gibt, Stile einzubringen.
Es ist wahrscheinlich erwähnenswert, dass der DOM, den Sie per slot platzieren, wie üblich von „externem“ CSS gestaltet werden kann. style-able from “outside” CSS.
Das ist ein wirklich seltsames Problem. Ich mag den Shadow DOM, weil er das ist, was wir auf der Webplattform den gekapselten Stilen am nächsten kommt, was definitiv eine gute Idee ist. Aber mir gefallen keine dieser Styling-Lösungen. Sie zwingen mich alle dazu, darüber nachzudenken, welche Art von Styling-API ich anbieten möchte und sie zu dokumentieren, während sie keine bestimmte Konsistenz über Komponenten hinweg fördern.
Für mich ist der DOM bereits eine Styling-API. Ich mag den gekapselten Schutz, aber es sollte eine einfache Möglichkeit geben, dort hineinzugreifen und Dinge zu gestalten, wenn ich es möchte. Es scheint, als gäbe es eine sehr einfache CSS-einzige Möglichkeit, hineinzugreifen und dennoch den Kaskadeneffekt usw. zu nutzen. Vielleicht reicht der mit Bindestrichen getrennte benutzerdefinierte Elementname aus? my-custom-elemement li { }. Oder vielleicht ist es expliziter, wie @shadow my-custom-element li { }. Ich denke einfach, es sollte einfacher sein. Constructable Stylesheets scheinen auch keinen Schritt in Richtung einer Vereinfachung zu machen.
Als ich das letzte Mal über das Styling von Web Components nachgedacht habe, habe ich nur versucht herauszufinden, wie es überhaupt funktioniert, und nicht, wie man Styling-Optionen für Verbraucher der Komponente bereitstellt.
Kommt das im täglichen Arbeitsablauf tatsächlich als Problem auf?
Ich sehe in diesem Thread (noch) keine besonders guten Optionen für die Styling-Herangehensweise. Wenn ich Dave wäre, würde ich mich vielleicht nur dafür entscheiden, nichts zu tun. Bieten Sie minimales Styling an, und wenn Leute es gestalten wollen, können sie es tun, wie sie wollen, aus ihrer Kopie der Komponente. Oder sie können die Stile „erzwingen“, was bedeutet, dass Sie die volle Freiheit haben.
Ich habe gerade angefangen, mich mit dem Thema Shadow DOM zu beschäftigen und habe mir vor ein paar Tagen dieselbe Frage gestellt.
Ich denke, der „@shadow name-of-element …“ ist eine großartige Lösung.
Warum schlagen Sie es nicht der CSS-Standardisierung vor?
Dies ist auch einer meiner Hauptkritikpunkte am Shadow DOM. Ich bin für Kapselung und es ist für mich völlig vernünftig, dass intern in einer Komponente definierte Stile nicht nach außen dringen. Oftmals möchte ich jedoch, dass globale Stile hineinkommen (nicht nur die grundlegenden erbbaren Eigenschaften von z.B.
color). Ja, Custom Properties sind eine Lösung, und::part()ist eine weitere (die dem Styling der Interna von UA-bereitgestellten Komponenten, wie z.B. Bereichseingaben und Mediensteuerungen, ähnelt, z.B.::-webkit-slider-runnable-track). Das Problem ist, dass diese die Angriffsfläche der API für jede Komponente erhöhen und es keine garantierte Konsistenz bei den Namenskonventionen gibt.Nehmen wir an, ich möchte alle
<button>s auf einer Seite gleich gestalten. Im Light DOM kann ich einfachAber stellen wir uns vor, es gibt Schaltflächen in verschiedenen benutzerdefinierten Elementen von verschiedenen Quellen, ich muss alle Eigenschaften dieser Komponenten kennen. Die Regeln werden dann so etwas wie
Das ist ein Wartungsalbtraum. Und vielleicht hat eine dieser Komponenten keine Eigenschaft zum Beispiel für die Einstellung des Radius freigegeben, sodass sie nicht mit unserem Designsystem übereinstimmen.
Kapselung führt nur dann zu Wiederverwendbarkeit, wenn wir nicht versucht sind, in Komponenten hineinzugreifen und sie neu zu implementieren oder zu forken, um unseren Bedürfnissen zu entsprechen.
Der eingestellte CSS
/deep/Kombinator hätte die Last der Wartung globaler Stile für benutzerdefinierte Elemente mit Shadow-Roots nur geringfügig verringert.Aus diesem Grund erstelle ich benutzerdefinierte Elemente ohne Shadow-Roots (Vanilla mit Lit-Element). Shadow-Roots sind jedoch nützlich, wenn es um die ID-Kapselung geht, sodass ich diese vermisse.
Die Lösung, die ich gerne sehen würde, ist eine Option zum
attachShadow(). Wie die Angabe von{mode: "open"}, um Skriptzugriff auf Shadow-Roots zu ermöglichen, würde das Übergeben einer Option (vielleicht{mode: "open", styles: "inherit"}), die Seitenstilen erlaubt, in Shadow-Roots zu fließen, es benutzerdefinierten Elementautoren ermöglichen, sich für globales Styling zu entscheiden, ohne bestehende Implementierungen zu brechen. Dies würde keine zusätzliche Syntax auf der CSS-Seite für die Verbraucher der Komponente erfordern, obwohl es möglicherweise Fragen der Spezifität gibt. Wenn ich alle gestaltbaren Schaltflächen gestalten möchte, bräuchte ich nur einen einfachen Selektor und müsste nicht über benutzerdefinierte Elemente nachdenken. Stile innerhalb des Elements würden weiterhin nicht nach außen dringen.Ich begann, benutzerdefinierte Web-Elemente zu gestalten, als ich meine Mimcss-Bibliothek zur Unterstützung dieser Elemente erstellte. Ich denke auch, dass der aktuelle Ansatz problematisch ist. Das Hauptproblem, das ich damit habe, ist, dass reguläre, auf globaler Ebene definierte Stile nicht auf den Shadow DOM angewendet werden. Ich halte das wirklich für einen Fehler. Die Tatsache, dass benutzerdefinierte CSS-Eigenschaften den Shadow DOM durchdringen, ist noch verwirrender: Wenn benutzerdefinierte CSS-Eigenschaften dies tun, warum dann nicht die regulären Stile?
Benutzerdefinierte Web-Elemente werden definitiv zum Ausliefern von Komponentbibliotheken verwendet. Als Bibliotheksautor möchte ich, dass meine Komponenten leicht das Erscheinungsbild der Host-Anwendung annehmen. In jeder Komponente wird es wahrscheinlich einige „interne“ UI-Aspekte und Mechaniken geben, die ich so gestalten möchte, wie ich es als Bibliotheksautor möchte, aber der Rest (wahrscheinlich eine Mehrheit) sollte die Stile der Host-Anwendung widerspiegeln.
Für mich bedeutet Kapselung von unter dem Shadow-Root definierten Stilen, dass sie nicht nach außen dringen: von den Stilen meiner Komponente zur Host-Anwendung. Das heißt, ich möchte nur eine Einweg-Kapselung sehen.
Was Constructable Stylesheets betrifft, so handelt es sich ausschließlich um eine Optimierungsfunktion. Wenn Sie mehrere Instanzen eines benutzerdefinierten Web-Elements haben, werden alle Stile nur einmal definiert, aber von allen Elementinstanzen „übernommen“. Die Tatsache, dass ein Constructable Stylesheet zwischen dem Dokument und den Instanzen benutzerdefinierter Web-Elemente „geteilt“ werden kann, ist schön, wenn das benutzerdefinierte Web-Element zusammen mit der Anwendung erstellt wird. Wenn benutzerdefinierte Web-Elemente jedoch aus einer Drittanbieterbibliothek stammen, ist dieses Teilen nutzlos. Der Bibliotheksentwickler weiß nicht, welche vom Dokument übernommenen Stylesheets von den Komponenten übernommen werden sollten.