Håll delade designtokens i sidans CSS, exponera komponentspecifika variabler som styling-API och koppla ihop dem med en liten mappning som ägs av sidan. Den här handledningen bygger en lokal Mac-demo som håller dessa ansvarsområden åtskilda.
Vad hör till sidan och vad hör till komponenten?
För den som redigerar en skriven webbsida på en Mac är den konkreta uppgiften att ge en återanvändbar komponent ett tema utan att göra dess implementation beroende av sidans tokene namn. Exemplet nedan använder en syntetisk orbit-tile-komponent som innehåller en abstrakt form och en kort etikett.
En designtoken och en publik komponentvariabel kan båda vara anpassade CSS-egenskaper. Skillnaden ligger i det kontrakt du dokumenterar. Vanliga oregistrerade anpassade egenskaper deltar i kaskaden och ärver värden; när de deklareras på :root blir de tillgängliga genom arv i hela dokumentet. Det finns inget särskilt CSS-nyckelord som gör en egenskap till en designtoken. Använda anpassade CSS-egenskaper (variabler)
Använd den här ansvarstabellen för att avgöra var en deklaration hör hemma. Namnen är illustrativa och gäller bara det här exemplet.
| Lager | Exempel | Ansvar |
|---|---|---|
| Sidans designtokens | --scene-accent, --scene-rounding |
Delade visuella val för den skrivna sidan |
| Sidans integrationsregler | En regel som riktas mot orbit-tile |
Översätta sidans val till komponentens API |
| Publika komponentvariabler | --orbit-tile-fill, --orbit-tile-radius |
Dokumenterade reglage som är tillgängliga för användare |
| Komponentens implementation | .shape, layoutregler, bokstavliga standardvärden |
Återge komponenten utan att kräva sidans tokens |
Det användbara testet är portabilitet: skulle en annan sida kunna tillhandahålla token med andra namn och ändå använda samma komponent oförändrad? Med en mappning som ägs av sidan skulle det gå. Den nya sidan skulle mappa sina egna tokens till samma publika komponentvariabler.
Hur passerar stylingkontraktet genom Shadow DOM?
Shadow DOM skiljer selektormatchning från arv. En sidselektor kan vanligtvis inte välja en intern form genom skugggränsen. Ärva egenskapsvärden kan fortfarande nå den via värdeelementet. CSS Shadow-specifikationen beskriver det utplattade elementträd som används för den här relationen; separata selektorträd tar inte bort arv. CSS Shadow Module Level 1
Låt de publika variablerna vara oinställda inuti komponenten och ange standardvärden där de används. Till exempel accepterar background-color: var(--orbit-tile-fill, #667085) ett ärvt värde från användaren samtidigt som den tillhandahåller ett fristående standardvärde. Om du i stället deklarerar --orbit-tile-fill: #667085 på :host får värdeelementet ett eget värde, vilket blockerar ett värde som ärvs från en förfader. En användare kan fortfarande rikta in sig direkt på värdelementet. Styling av webbkomponenter
Dokumentera bara två publika reglage i det här exemplet:
| Publik variabel | Accepterat värde i det här exemplet | Standardvärde om den saknas | Effekt |
|---|---|---|---|
--orbit-tile-fill |
En giltig CSS-färg | #667085 |
Formens bakgrundsfärg |
--orbit-tile-radius |
En icke-negativ längd eller procentsats | 1rem |
Formens hörnradie |
Dessa accepterade värden utgör en API-överenskommelse. Grundimplementationen registrerar eller validerar dem inte automatiskt. Interna klassnamn är implementationsdetaljer, så sidans författare bör anpassa de publika variablerna i stället för att förlita sig på .shape.
Bygg ett komplett lokalt exempel på din Mac
Använd en textredigerare för oformaterad text och en webbläsare som stöder anpassade CSS-egenskaper, Shadow DOM och autonoma anpassade element. Exemplet använder ett autonomt element som utökar HTMLElement; MDN skiljer den metoden från anpassade inbyggda element, som Safari inte planerar att stödja. Använda anpassade element
I TextEdit väljer du Arkiv > Nytt och sedan Format > Gör till oformaterad text. Klistra in hela dokumentet nedan och spara det som token-demo.html. Välj Använd .html om du får frågan. När du öppnar filen igen för redigering väljer du Ignorera kommandon för RTF i öppningsdialogrutan eller aktiverar Visa HTML-filer som HTML-kod i stället för formaterad text i inställningarna. Arbeta med HTML-dokument i TextEdit på Mac
Dokumentets första stilmall äger tokens, integrationsregler och sidlayout. Komponenten skapar en separat stilmall inuti sin skuggrot. HTML definierar elementet style som ett sätt att bädda in CSS; genom att placera all källkod i en fil blir resursupplägget i exemplet tydligt. HTML-standarden: style-elementet
<!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>
Öppna den sparade filen i Safari, Chrome eller Firefox. Exemplet har inga externa skript, teckensnitt, bilder eller stilmallar. JavaScript-koden klarade en syntaxkontroll; de visuella resultaten nedan är förväntade utfall utifrån deklarationerna, inte en rapport från körning i en webbläsare.
| Instans | Förväntad form | Värdeväg |
|---|---|---|
Sample A |
Blå, med hörn på 12px |
Rotens tokens → mappning på värdelementet → komponent |
Sample B |
Grön, med hörn på 24px |
Sektionens tokens → mappning på värdelementet → komponent |
Sample C |
Orange cirkel | Instansöverskuggning → komponent |
Lägg märke till att komponentens JavaScript inte innehåller några referenser till --scene-*. Dess stilmall använder bara de publika namnen --orbit-tile-*. Sidan kan organisera om sina tematermer utan att komponenten behöver ändras.
Var bör mappningen från tokens till komponent ske?
Mappa värden där det avsedda temat är tillgängligt. I den här demon körs regeln orbit-tile på varje värdelement. Det gör att det andra värdeelementet kan slå upp --scene-accent efter att ha ärvt sektionens gröna värde.
Undvik att flytta den mappningen till :root utan att ta hänsyn till när värdet beräknas. Om --orbit-tile-fill: var(--scene-accent) beräknas där ärver underordnade element dess beräknade värde. Om du bara ändrar --scene-accent i en senare sektion skapas inte det ärvda aliaset på nytt. Anpassade egenskaper löser sina var()-referenser innan deras beräknade värden ärvs. CSS Custom Properties for Cascading Variables Module Level 1
Det praktiska beslutet gäller omfattningen: använd en mappning på värdelementet när varje instans ska följa sidans omgivande tokens. Om en hel region avsiktligt delar ett publikt komponentvärde kan det passa att deklarera den publika variabeln på regionen, men ta då bort mappningen på värdelementet för den variabeln så att den inte ersätter det ärvda värdet.
För återkommande intern användning kan ett implementationsalias samla reservdeklarationer på ett ställe. Ett namn som --_orbit-tile-fill kan signalera en intern konvention, men understrecket skapar ingen faktisk sekretess. Direkt användning, som i det fullständiga exemplet, är lättare att följa när varje värde används en gång. Styling av webbkomponenter
Hur felsöker du en överskuggning som inte fungerar?
Använd de tre instanserna som ett litet kontraktstest. Ändra en deklaration i taget, spara och läs in sidan igen. De här kontrollerna hjälper dig att skilja mellan en saknad resurs, ett arvproblem och ett ogiltigt värde.
- Ändra rotens accentfärg till
#7251a1. Förvänta dig att endastSample Afår den färgen; sektionen och instansen har egna val. - Ändra sektionens accentfärg till
#32758a. Förvänta dig attSample Bändras utan att du redigerar komponentens kod. - Ta bort hela integrationsmappningen. Förvänta dig att
Sample AochSample Banvänder komponentens grå fyllning och radien1rem;Sample Cbehåller sina uttryckliga publika överskuggningar. - Återställ mappningen innan du fortsätter med andra experiment.
Om alla former försvinner kontrollerar du först att dokumentet är sparat som HTML och att skriptet är intakt. Om etiketterna visas men formerna saknar stil kontrollerar du komponentens stilmall. En dokumentstilmall påverkar inte skuggelement med vanliga selektorer; implementationen måste koppla sina interna stilar till skuggträdet. MDN beskriver både inbäddade stilar och konstruerade stilmallar för detta ändamål. Använda Shadow DOM
Om bara en överskuggning från en förfader misslyckas letar du efter en deklaration av den publika variabeln direkt på värdelementet. I det här exemplet är integrationsmappningen en sådan deklaration. Ändra antingen sidans token som matar den, överskugga den publika variabeln på instansen eller ta bort mappningen när kontraktet är att förfäder ska styra temat via publika variabler.
Om en form blir genomskinlig efter att du angett --orbit-tile-fill: 12px hjälper reservvärdet inte. Variabeln finns, men dess ersatta värde är ogiltigt för background-color. Deklarationen blir ogiltig när värdet beräknas; CSS återgår inte till en tidigare bakgrundsdeklaration. Ta bort tilldelningen eller ange en giltig färg. CSS Custom Properties for Cascading Variables Module Level 1
Bör publika variabler använda @property?
Registrering är valfri i det här kontraktet. @property lägger till syntaxbegränsningar, ett initialvärde och ett uttryckligt beteende för arv. MDN anger att funktionen har Baseline 2024 och har funnits i aktuella webbläsare sedan juli 2024, men varnar för att äldre webbläsare kanske saknar stöd. Det fullständiga exemplet gör inte registrering till ett krav. CSS-at-regeln @property
Om du inför registrering ska du samordna den på dokumentnivå. Chromes implementationsdokumentation uppger att registreringar inuti skuggrotar ignoreras; rapporten är daterad augusti 2024, så behandla detta som en dokumenterad interoperabilitetsgräns snarare än som bevis på ett nytt webbläsartest. Den väg som beskrivs som stödd där är registrering på dokumentnivå, där komponenten använder egenskapen över gränsen. Författardefinierade CSS-namn och Shadow DOM: i specifikationen och i praktiken
Registrering ändrar också beteendet. Om du anger inherits: false bryts arvet från värdelement till form i exemplet. En registrerad initialfärg innebär att en oinställd egenskap får den färgen, så en reservlösning i var() som förbrukar värdet blir inte längre standarden när värdet saknas. Behåll inherits: true för den här designen och välj medvetet vilken mekanism som ska äga standardvärdet. CSS-at-regeln @property
Det färdiga kontraktet ska göra det möjligt för sidans författare att förklara varje värdes väg: ett delat sidval, en mappning till en dokumenterad komponentkontroll och ett reservvärde som ägs av komponenten. Håll mappningen nära det avsedda temaomfånget, låt publika indata som ska ärvas vara oinställda internt och behåll exemplet med tre instanser när du ändrar API:t.
Källor
- Använda anpassade CSS-egenskaper (variabler) — MDN Web Docs.
- CSS Shadow Module Level 1 — W3C CSS Working Group.
- Styling av webbkomponenter — Chrome for Developers.
- Använda anpassade element — MDN Web Docs.
- Arbeta med HTML-dokument i TextEdit på Mac — Apple Support.
- HTML-standarden — WHATWG.
- CSS Custom Properties for Cascading Variables Module Level 1 — W3C.
- Använda Shadow DOM — MDN Web Docs.
- CSS-at-regeln @property — MDN Web Docs.
- Författardefinierade CSS-namn och Shadow DOM: i specifikationen och i praktiken — Chrome for Developers.