Gemeinsame Design-Tokens im CSS der Seite verwalten, komponentenspezifische Variablen als Styling-API bereitstellen und sie mit einer kleinen, seiteneigenen Zuordnung verbinden. Dieses Tutorial erstellt eine lokale Mac-Demo, in der diese Zuständigkeiten getrennt bleiben.
Was gehört zur Seite und was zur Komponente?
Wer eine gestaltete Webseite auf einem Mac bearbeitet, möchte eine wiederverwendbare Komponente mit einem Theme versehen, ohne ihre Implementierung von den Token-Namen der Seite abhängig zu machen. Das folgende Beispiel verwendet eine synthetische Komponente orbit-tile, die eine abstrakte Form und eine kurze Beschriftung enthält.
Ein Design-Token und eine öffentliche Komponentenvariable können beide CSS-Custom-Properties sein. Der Unterschied ergibt sich aus dem Vertrag, den Sie dokumentieren. Gewöhnliche, nicht registrierte Custom-Properties nehmen an der Kaskade teil und werden vererbt. Wenn Sie sie auf :root deklarieren, stehen sie durch Vererbung im gesamten Dokument zur Verfügung. Es gibt kein spezielles CSS-Schlüsselwort, das eine Property zu einem Design-Token macht. CSS-Custom-Properties (Variablen) verwenden
Verwenden Sie diese Zuständigkeitstabelle, um zu entscheiden, wohin eine Deklaration gehört. Die Namen dienen der Veranschaulichung und gelten nur für dieses Beispiel.
| Ebene | Beispiel | Zuständigkeit |
|---|---|---|
| Design-Tokens der Seite | --scene-accent, --scene-rounding |
Gemeinsame visuelle Entscheidungen für die gestaltete Seite |
| Integrationsregeln der Seite | Eine Regel, die auf orbit-tile zielt |
Seitenentscheidungen in die API der Komponente übersetzen |
| Öffentliche Komponentenvariablen | --orbit-tile-fill, --orbit-tile-radius |
Dokumentierte Steuerelemente für Verbraucher |
| Komponentenimplementierung | .shape, Layoutregeln, feste Standardwerte |
Die Komponente darstellen, ohne Seitentokens vorauszusetzen |
Der nützliche Test ist die Portabilität: Könnte eine andere Seite andere Token-Namen verwenden und dabei dieselbe Komponente unverändert einsetzen? Mit einer seiteneigenen Zuordnung wäre das möglich. Die neue Seite würde ihre eigenen Tokens denselben öffentlichen Komponentenvariablen zuordnen.
Wie überquert der Styling-Vertrag die Shadow-DOM-Grenze?
Shadow DOM trennt die Selektoranwendung von der Vererbung. Ein Seiten-Selektor kann eine interne Form normalerweise nicht über die Shadow-Grenze hinweg auswählen. Geerbte Property-Werte können sie jedoch weiterhin über das Host-Element erreichen. Die CSS-Shadow-Spezifikation beschreibt den abgeflachten Elementbaum, der dieser Beziehung zugrunde liegt; getrennte Selektorbäume heben die Vererbung nicht auf. CSS Shadow Module Level 1
Lassen Sie die öffentlichen Variablen innerhalb der Komponente ungesetzt und geben Sie Standardwerte dort an, wo sie verwendet werden. Zum Beispiel akzeptiert background-color: var(--orbit-tile-fill, #667085) einen vom Verbraucher geerbten Wert und stellt zugleich einen eigenständigen Standardwert bereit. Würde stattdessen --orbit-tile-fill: #667085 auf :host deklariert, erhielte das Host-Element einen eigenen Wert und würde einen von einem Vorfahren geerbten Wert blockieren. Ein Verbraucher könnte das Host-Element weiterhin direkt ansprechen. Web Components gestalten
Dokumentieren Sie für dieses Beispiel nur zwei öffentliche Steuerelemente:
| Öffentliche Variable | Für dieses Beispiel akzeptierter Wert | Standardwert, falls nicht vorhanden | Wirkung |
|---|---|---|---|
--orbit-tile-fill |
Eine gültige CSS-Farbe | #667085 |
Hintergrundfarbe der Form |
--orbit-tile-radius |
Ein nichtnegativer Längenwert oder Prozentsatz | 1rem |
Eckenradius der Form |
Diese akzeptierten Werte bilden eine API-Vereinbarung. Die grundlegende Implementierung registriert oder validiert sie nicht automatisch. Interne Klassennamen sind Implementierungsdetails. Seitenautoren sollten daher die öffentlichen Variablen anpassen, statt sich auf .shape zu verlassen.
Erstellen Sie ein vollständiges lokales Beispiel auf Ihrem Mac
Verwenden Sie einen Nur-Text-Editor und einen Browser, der CSS-Custom-Properties, Shadow DOM und autonome benutzerdefinierte Elemente unterstützt. In diesem Beispiel wird ein autonomes Element verwendet, das HTMLElement erweitert. MDN unterscheidet diesen Ansatz von angepassten integrierten Elementen, die Safari laut Planung nicht unterstützen wird. Benutzerdefinierte Elemente verwenden
Wählen Sie in TextEdit Datei > Neu und dann Format > In reinen Text umwandeln. Fügen Sie das vollständige Dokument unten ein und speichern Sie es als token-demo.html. Wenn Sie dazu aufgefordert werden, wählen Sie .html verwenden. Wählen Sie beim erneuten Öffnen zum Bearbeiten im Öffnen-Dialog Rich-Text-Befehle ignorieren oder aktivieren Sie in den Einstellungen HTML-Dateien als HTML-Code statt als formatierten Text anzeigen. Mit HTML-Dokumenten in TextEdit auf dem Mac arbeiten
Das erste Stylesheet des Dokuments enthält Tokens, Integrationsregeln und das Seitenlayout. Die Komponente erstellt ein separates Stylesheet in ihrem Shadow-Root. HTML definiert das Element style als Möglichkeit, CSS einzubetten. Wenn der gesamte Quelltext in einer Datei steht, bleibt die Einrichtung der Ressourcen in diesem Beispiel explizit. HTML-Standard: Das style-Element
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Orbit tile token demo</title>
<style>
/* Page-owned shared tokens */
:root {
--scene-accent: #4058b8;
--scene-rounding: 12px;
}
/* Page-owned integration mapping */
orbit-tile {
--orbit-tile-fill: var(--scene-accent);
--orbit-tile-radius: var(--scene-rounding);
}
/* A local page theme */
.alternate {
--scene-accent: #276f64;
--scene-rounding: 24px;
}
/* An intentional override for one component instance */
orbit-tile.special {
--orbit-tile-fill: #a65b20;
--orbit-tile-radius: 50%;
}
body {
max-width: 36rem;
margin: 3rem auto;
padding: 0 1rem;
font: 1rem/1.5 system-ui, sans-serif;
}
main { display: grid; gap: 1rem; }
</style>
</head>
<body>
<main>
<orbit-tile>Sample A</orbit-tile>
<section class="alternate" aria-label="Alternate samples">
<orbit-tile>Sample B</orbit-tile>
</section>
<orbit-tile class="special">Sample C</orbit-tile>
</main>
<script>
class OrbitTile extends HTMLElement {
constructor() {
super();
const root = this.attachShadow({ mode: 'open' });
const style = document.createElement('style');
style.textContent = `
:host { display: block; }
.tile {
display: flex;
align-items: center;
gap: 1rem;
padding: 1rem;
background: #f2f4f6;
color: #202630;
}
.shape {
display: block;
width: 4rem;
height: 4rem;
flex: 0 0 4rem;
background-color: var(--orbit-tile-fill, #667085);
border-radius: var(--orbit-tile-radius, 1rem);
}
`;
const tile = document.createElement('div');
tile.className = 'tile';
const shape = document.createElement('span');
shape.className = 'shape';
shape.setAttribute('aria-hidden', 'true');
tile.append(shape, document.createElement('slot'));
root.append(style, tile);
}
}
customElements.define('orbit-tile', OrbitTile);
</script>
</body>
</html>
Öffnen Sie die gespeicherte Datei in Safari, Chrome oder Firefox. Das Beispiel benötigt keine externen Skripte, Schriftarten, Bilder oder Stylesheets. Die JavaScript-Syntaxprüfung war erfolgreich. Die folgenden visuellen Ergebnisse sind aus den Deklarationen abgeleitete erwartete Resultate und kein Bericht über eine Ausführung im Browser.
| Instanz | Erwartete Form | Wertpfad |
|---|---|---|
Sample A |
Blau, mit 12px Eckenradius |
Root-Tokens → Host-Zuordnung → Komponente |
Sample B |
Grün, mit 24px Eckenradius |
Abschnitts-Tokens → Host-Zuordnung → Komponente |
Sample C |
Orangefarbener Kreis | Instanzüberschreibung → Komponente |
Beachten Sie, dass das JavaScript der Komponente keine Verweise auf --scene-* enthält. Ihr Stylesheet verwendet ausschließlich die öffentlichen Namen --orbit-tile-*. Die Seite kann ihr Theme-Vokabular neu ordnen, ohne die Komponente zu ändern.
Wo sollte die Zuordnung von Tokens zu Komponenten stattfinden?
Ordnen Sie Werte dort zu, wo das gewünschte Theme verfügbar ist. In dieser Demo wird die Regel orbit-tile auf jedes Host-Element angewendet. Dadurch kann das zweite Host-Element --scene-accent auflösen, nachdem es den grünen Wert des Abschnitts geerbt hat.
Verschieben Sie diese Zuordnung nicht ohne Rücksicht auf den Zeitpunkt der Auflösung nach :root. Wird --orbit-tile-fill: var(--scene-accent) dort berechnet, erben die Nachfahren seinen aufgelösten Wert. Wenn nur --scene-accent in einem späteren Abschnitt geändert wird, wird der geerbte Alias dadurch nicht neu gebildet. Custom-Properties lösen ihre var()-Verweise auf, bevor ihre berechneten Werte vererbt werden. CSS Custom Properties for Cascading Variables Module Level 1
Die praktische Entscheidung hängt vom Geltungsbereich ab: Verwenden Sie eine Zuordnung auf Host-Ebene, wenn jede Instanz den umgebenden Seitentokens folgen soll. Wenn ein ganzer Bereich absichtlich denselben öffentlichen Komponentenwert verwendet, kann es sinnvoll sein, diese öffentliche Variable auf dem Bereich zu deklarieren. Entfernen Sie dann die Host-Zuordnung für diese Variable, damit sie den geerbten Wert nicht ersetzt.
Bei wiederholter interner Verwendung kann ein Implementierungsalias die Fallback-Deklarationen zusammenhalten. Ein Name wie --_orbit-tile-fill kann eine interne Konvention signalisieren, doch der Unterstrich sorgt nicht für erzwungene Privatheit. Wie im vollständigen Beispiel ist die direkte Verwendung leichter nachzuvollziehen, wenn jeder Wert nur einmal verwendet wird. Web Components gestalten
Wie lässt sich eine nicht funktionierende Überschreibung diagnostizieren?
Verwenden Sie die drei Instanzen als kleinen Vertragstest. Ändern Sie immer nur eine Deklaration, speichern Sie die Datei und laden Sie sie neu. Mit diesen Prüfungen können Sie zwischen einer fehlenden Ressource, einem Vererbungsproblem und einem ungültigen Wert unterscheiden.
- Ändern Sie den Akzent auf Root-Ebene zu
#7251a1. Erwartung: NurSample Aübernimmt den Wert; für den Abschnitt und die Instanz gelten eigene Werte. - Ändern Sie den Akzent des Abschnitts zu
#32758a. Erwartung:Sample Bändert sich, ohne dass Sie den Komponentencode bearbeiten müssen. - Entfernen Sie die gesamte Integrationszuordnung. Erwartung:
Sample AundSample Bverwenden die graue Füllfarbe und den Radius1remder Komponente;Sample Cbehält seine expliziten öffentlichen Überschreibungen. - Stellen Sie die Zuordnung wieder her, bevor Sie mit anderen Experimenten fortfahren.
Wenn alle Formen verschwinden, überprüfen Sie zuerst, ob das Dokument als HTML gespeichert wurde und das Skript intakt ist. Wenn die Beschriftungen erscheinen, die Formen aber ungestylt sind, untersuchen Sie das Stylesheet der Komponente. Ein Dokument-Stylesheet gestaltet Shadow-Nachfahren nicht mit gewöhnlichen Selektoren. Die Implementierung muss ihre internen Stile an den Shadow-Baum anhängen. MDN dokumentiert dafür sowohl eingebettete Stile als auch konstruierte Stylesheets. Shadow DOM verwenden
Wenn nur eine Überschreibung durch einen Vorfahren fehlschlägt, suchen Sie nach einer Deklaration der öffentlichen Variable direkt auf dem Host-Element. In diesem Beispiel ist die Integrationszuordnung eine solche Deklaration. Ändern Sie entweder das Seitentoken, das ihr zugrunde liegt, überschreiben Sie die öffentliche Variable auf der Instanz oder entfernen Sie die Zuordnung, wenn das beabsichtigte Vertragsmodell öffentliche Themes auf Vorfahrenebene vorsieht.
Wenn eine Form transparent wird, nachdem Sie --orbit-tile-fill: 12px zugewiesen haben, kann der Fallback das nicht beheben. Die Variable ist vorhanden, aber ihr eingesetzter Wert ist für background-color ungültig. Diese Deklaration wird zum Zeitpunkt der Berechnung ungültig; sie fällt nicht auf eine frühere Hintergrunddeklaration zurück. Entfernen Sie die Zuweisung oder geben Sie eine gültige Farbe an. CSS Custom Properties for Cascading Variables Module Level 1
Sollten öffentliche Variablen @property verwenden?
Für diesen Vertrag ist die Registrierung optional. @property legt Syntaxbeschränkungen, einen Anfangswert und ein explizites Vererbungsverhalten fest. Laut MDN gehört die Funktion seit 2024 zur Baseline und ist seit Juli 2024 in aktuellen Browsern verfügbar. Ältere Browser unterstützen sie möglicherweise nicht. Im vollständigen Beispiel ist die Registrierung keine Voraussetzung. @property CSS-At-Regel
Wenn Sie eine Registrierung einführen, stimmen Sie sie auf Dokumentebene ab. Laut der Implementierungsdokumentation von Chrome werden Registrierungen innerhalb von Shadow-Roots ignoriert. Der Bericht stammt vom August 2024. Betrachten Sie ihn daher als dokumentierte Interoperabilitätsgrenze und nicht als Beleg für einen aktuellen Browser-Test. Der dort beschriebene unterstützte Weg ist eine Registrierung auf Dokumentebene, wobei die Komponente die Property über die Grenze hinweg verwendet. Vom Autor definierte CSS-Namen und Shadow DOM: in der Spezifikation und in der Praxis
Die Registrierung verändert außerdem das Verhalten. inherits: false würde die Vererbung vom Host-Element zur Form im Beispiel unterbrechen. Ein registrierter Anfangswert für eine Farbe bedeutet, dass eine nicht gesetzte Property diese Farbe hat. Ein Fallback für var() an der Verwendungsstelle ist dann nicht mehr der Standardwert für einen fehlenden Wert. Belassen Sie inherits: true für dieses Design und entscheiden Sie bewusst, welcher Mechanismus den Standardwert vorgibt. @property CSS-At-Regel
Mit dem fertigen Vertrag sollte ein Seitenautor den Pfad jedes Werts erklären können: eine gemeinsame Seitenentscheidung, eine Zuordnung zu einem dokumentierten Komponenten-Steuerelement und ein von der Komponente bereitgestellter Fallback. Halten Sie die Zuordnung nahe am vorgesehenen Theme-Geltungsbereich, lassen Sie geerbte öffentliche Eingaben intern ungesetzt und behalten Sie das Beispiel mit den drei Instanzen bei, wenn Sie die API überarbeiten.
Quellen
- CSS-Custom-Properties (Variablen) verwenden — MDN Web Docs.
- CSS Shadow Module Level 1 — W3C CSS Working Group.
- Web Components gestalten — Chrome for Developers.
- Benutzerdefinierte Elemente verwenden — MDN Web Docs.
- Mit HTML-Dokumenten in TextEdit auf dem Mac arbeiten — Apple Support.
- HTML-Standard — WHATWG.
- CSS Custom Properties for Cascading Variables Module Level 1 — W3C.
- Shadow DOM verwenden — MDN Web Docs.
- @property CSS-At-Regel — MDN Web Docs.
- Vom Autor definierte CSS-Namen und Shadow DOM: in der Spezifikation und in der Praxis — Chrome for Developers.