Aktualisiert 11. Juli 2026

Semantische Tokens für den Theme-Wechsel

Theme-Wechsel ist ein Benennungsproblem, bevor es ein CSS-Problem ist. Dark mode design tokens sind semantische Rollen — background, surface, text-primary —, bei denen jede Rolle zwei Werte hält, einen pro Theme, und Komponenten verweisen nur auf den Rollennamen. Wechsle das Theme, und jeder Verweis wird auf einen Schlag neu aufgelöst; keine Komponente trägt eine Meinung darüber, in welchem Modus sie sich befindet. Das technische Risiko ist nicht der Wechsel, sondern das Mapping: die Rollen-zu-Wert-Tabelle eines Dark-Themes ist kein Spiegelbild der hellen, also muss sie abgeleitet und neu geprüft werden, niemals umgeklappt.

Der geschichtete Aufbau darunter passt in einen Absatz: Primitive Tokens benennen das Rohmaterial (die Stufen der Farbrampe — brand-600, neutral-100), semantische Tokens benennen UI-Aufgaben und zeigen auf Primitive, und Komponenten konsumieren nur Semantik. Die Benennungs-Argumente und die Mechanik in der Design-Datei haben ihre eigenen Guides; dieser Artikel — Teil unseres Dark-Mode-Guides — handelt davon, was die semantische Ebene tut, wenn ein zweites Theme dazukommt.

Warum braucht jede Rolle zwei Werte?

Weil die Bedeutung einer Rolle stabil ist und ihr Wert nicht. background bedeutet in jedem Theme „die Ruhefarbe der Seite”; der Wert, der diese Aufgabe erfüllt, ist im Light Mode fast weiß und im Dark Mode fast schwarz. Die semantische Ebene ist die Theme-Grenze: alles darüber — Komponenten, Layouts, Screens — bleibt theme-blind, und alles darunter ändert sich komplett.

Das ist auch der intuitive Grund, warum das Muster für die Menschen funktioniert, die es benutzen. Wer in Rollen denkt — Designerin oder Entwickler —, fragt wofür ist diese Fläche da, was eine Antwort hat; wer in Werten denkt, fragt welches Grau ist das, was zwei Antworten hat, die von Hand synchron gehalten werden müssen. Namen, die eine Aufgabe statt eines Werts versprechen, machen das zweite Theme zu einer Datenänderung statt zu einem zweiten Design.

Warum ist das Dark-Mapping kein Spiegelbild des hellen?

Das verlockende mentale Modell ist, die Skala umzuklappen — wenn der Light Mode neutral-100 für die Seite benutzt, nimmt der Dark Mode die Gegennummer. Das Mapping abzuleiten und zu prüfen liefert etwas Interessanteres. Sechs Rollen aus einer Palette mit der Ausgangsfarbe #2563eboklch(0.546 0.215 262.9):

RolleLightDark (abgeleitet)Was ein reines Spiegelbild sagen würde
backgroundneutral-100 (L ≈0.94)neutral-900 (L ≈0.22)neutral-800 — aber die Seite verankert sich am unteren Ende der Skala, damit die Elevations-Leiter darüber Platz hat
surface (Karte)neutral-50 (L ≈0.97)neutral-800 (L ≈0.28)neutral-900 — was die Karte unter die Seite absinken lassen und die Elevation umkehren würde
text-primaryneutral-800 (L ≈0.28)neutral-100 (L ≈0.94)neutral-100 — hält, obwohl von Hand abgestimmte Themes oft zu stark auf neutral-200 abmildern, was dünn wirkt
text-secondaryneutral-600 (L ≈0.47)neutral-300 (L ≈0.78)neutral-300 — das Spiegelbild hält
border-subtleneutral-200, dunkler als die Karteneutral-700, heller als die Kartedieselben Stufen — aber die Beziehung kehrt ihre Richtung um
accentbrand-600 (≈#3E65B5)oklch(0.70 0.14 262.9) aus der dunklen Farbrampebrand-300 der hellen Farbrampe — die komplett falsche Rampe

Drei Asymmetrien sind es wert, benannt zu werden. Erstens kreuzen background und surface ihre Spiegelbilder: erhöhte Flächen müssen im Dark Mode heller sein als das, worauf sie liegen, also landet die Karte auf der Helligkeitsskala über der Seite, obwohl das Spiegeln sie darunter platziert hätte. Zweitens der Text: neutral-200 auf der dunklen Seite übersteht das arithmetische Minimum immer noch (≈12:1 gegenüber der Anforderung von 4,5:1), aber heller Text auf Dunkel wirkt tendenziell dünner, als die Zahlen vermuten lassen — APCA, das die Polarität modelliert, meldet das Paar niedriger als sein Pendant im Light-Theme —, also landet die Ableitung eine Stufe heller, als Vorsicht wählen würde. Drittens stammt der dunkle Wert des Akzents überhaupt nicht aus der hellen Farbrampe: eine abgeleitete dunkle Palette folgt ihrer eigenen Helligkeitskurve mit einem um rund 20 % erhöhten Chroma, weil dunkle Umgebungen die wahrgenommene Farbigkeit dämpfen.

Die praktische Konsequenz: Die beiden Mappings sollten aus einer Ableitung entstehen, nicht als zwei Listen gepflegt werden. Der Token-Export von Scale Composer enthält eine semantic- und eine semantic-dark-Sektion, aus denselben Ausgangsfarben generiert — jede Rolle pro Theme neu abgeleitet, WCAG-Mindestwerte neu geprüft, APCA daneben ausgewiesen und onFill-Rollen neu verifiziert, denn eine Füllung, die im Light Mode weißen Text trug, will im Dark Mode womöglich dunklen Text.

Öffne den Export mit beiden semantischen Sektionen in Scale Composer — dieselben Rollennamen auf beiden Seiten, die dunklen Werte sichtbar kein Spiegelbild der hellen.

Token-Export mit den Sektionen semantic und semantic-dark nebeneinander, dieselben Rollennamen lösen sich zu unterschiedlichen, asymmetrischen Werten auf

Welche Muster für den Theme-Wechsel scheitern bei Skalierung?

Drei Muster kehren immer wieder, und alle drei scheitern auf dieselbe Weise — das Mapping wird verstreut, statt einmal deklariert.

dark:-Varianten pro Komponente. Tailwinds dark:-Präfix wiederholt den dunklen Wert an jeder Verwendungsstelle: bg-white dark:bg-gray-900 auf jeder Karte, in jeder Datei. Für eine kleine Website ist das in Ordnung — das ganze Mapping passt auf einen Bildschirm. Für ein System ist es eine Wartungssteuer: zu ändern, was „surface” im Dark Mode bedeutet, ist ein Suchen-und-Ersetzen über die gesamte Codebasis, und jede Komponente, die ihren dark:-Zwilling verpasst hat, wird in einem Theme kaputt ausgeliefert.

if (isDark) im Komponenten-Code. Theme-Bedingungen verlagern das Mapping in die Logik, wo es sich verzweigen, driften und der Prüfung entgehen kann. Eine Komponente, die fragt, welches Theme aktiv ist, hat eine Verantwortung übernommen, die die Token-Ebene bereits trägt.

Zwei Stylesheets. Eine dark.css, die neben einer light.css gepflegt wird, beginnt als Kopie und driftet ab der ersten Änderung, die nur eine Datei berührt. Nichts erzwingt, dass beide Dateien dieselben Fragen beantworten.

Wie tragen CSS Custom Properties den Wechsel?

Indem sie dieselben Namen unter einem Theme-Scope neu deklarieren. Komponenten verweisen auf die Custom Property; der Wert der Property hängt davon ab, welche Deklaration gerade gilt — die Mechanik sind CSS Custom Properties plus die Kaskade, nicht mehr.

:root {
  --color-background:   oklch(0.94 0.008 262.9);  /* neutral-100 */
  --color-surface:      oklch(0.97 0.005 262.9);  /* neutral-50  */
  --color-text-primary: oklch(0.28 0.02 262.9);   /* neutral-800 */
  --color-accent:       oklch(0.546 0.215 262.9); /* Marken-Kern */
}

[data-theme="dark"] {
  --color-background:   oklch(0.22 0.015 262.9);  /* neutral-900 */
  --color-surface:      oklch(0.28 0.02 262.9);   /* neutral-800 */
  --color-text-primary: oklch(0.94 0.008 262.9);  /* neutral-100 */
  --color-accent:       oklch(0.70 0.14 262.9);   /* dunkle Rampe */
}

.card {
  background: var(--color-surface);
  color: var(--color-text-primary);
}

Die .card-Regel ist der Punkt: sie erscheint einmal, nennt kein Theme und ist in beiden korrekt. Der Dark-Block kann ebenso an der Media Query prefers-color-scheme hängen, oder — das robuste Muster — die Query setzt den Standard und das Attribut überschreibt ihn; die Verdrahtungs-Details sind ein eigener Artikel. Welchen Auslöser du auch wählst, der CSS-Export aus einer Token-Quelle generiert beide Blöcke aus derselben Ableitung, und genau das hält die beiden Mappings davon ab, auseinanderzudriften.

Sieh zu, wie sich ein Wechsel auflöst

Dem Mapping vertraut man am leichtesten, nachdem man ihm beim Bewegen zugesehen hat. Schalte die Theme-Vorschau über dem vollständigen Rollensatz um — jede semantische Rolle löst sich auf einen Schlag neu auf, die Asymmetrien aus der Tabelle oben werden direkt sichtbar: die Karte bleibt heller als die Seite, der Akzent springt auf eine hellere Stufe einer neu abgeleiteten Rampe, nirgends Entscheidungen auf Komponentenebene.

Weiterlesen

  • Dark Mode ist keine Invertierung

    Dark-Mode-Design beginnt dort, wo Invertierung scheitert: umgekehrte Rollenlogik, kaputte Elevation, ausgelaugte Farben. Was es bedeutet, eine dunkle Palette aus denselben Ausgangsfarben abzuleiten.

  • prefers-color-scheme: Richtig eingesetzt in CSS

    Wie prefers-color-scheme funktioniert: die Media Query als Standard, ein data-theme-Override für den manuellen Umschalter, color-scheme und der Fix gegen das Aufblitzen des falschen Themes.