ein Codebase, mehrere Marken mit @theme und Custom Properties
White-Label-Produkte, Multi-Tenant-SaaS und Agenturen mit vielen Kunden stehen vor derselben Herausforderung: Wie bedient man mehrere Marken aus einem einzigen Codebase, ohne Klassennamen zu duplizieren und ohne den Build-Prozess zu verkomplizieren? Tailwind CSS Multi-Brand-Theming mit @theme und CSS Custom Properties ist die Antwort.
Inhaltsverzeichnis
- 1. Das Grundproblem bei Multi-Brand-Projekten
- 2. Design-Tokens als Fundament
- 3. @theme in Tailwind CSS v4 für Brand-Token
- 4. CSS Custom Properties als Theming-Layer
- 5. data-Attribute für Theme-Switching
- 6. Dark Mode im Multi-Brand-Kontext
- 7. Build-Pipeline für mehrere Brands
- 8. Ansätze im direkten Vergleich
- 9. Theme-Testing und visuelle Regressionstests
- 10. Zusammenfassung
- 11. FAQ
1. Das Grundproblem bei Multi-Brand-Projekten
Wer für mehrere Marken aus einem gemeinsamen Codebase heraus entwickelt, kennt die klassische Falle: Anfangs werden Farben und Typografie hart kodiert – text-blue-600 für Marke A, text-red-600 für Marke B. Mit jeder neuen Marke wächst die Zahl der bedingten Klassen, der if-Konstrukte in Templates und der separaten CSS-Dateien. Das Ergebnis ist ein Codebase, der schwer zu warten, noch schwerer zu testen und mit jeder neuen Marke exponentiell komplexer wird. Tailwind CSS Multi-Brand-Theming löst dieses Problem durch eine saubere Trennung zwischen Design-Token-Layer und Utility-Layer.
Die Kernidee ist einfach: Statt markenspezifische Farben direkt als Tailwind-Klassen zu verwenden, werden semantische Token definiert – --color-brand-primary, --color-brand-secondary, --font-brand. Tailwind-Klassen wie bg-brand-primary und text-brand-secondary verweisen auf diese Token. Wenn die Marke wechselt, ändern sich nur die CSS Custom Property-Werte hinter den Token – die Klassen in den Templates bleiben unverändert. Das ist der fundamentale Vorteil von Multi-Brand-Theming gegenüber hartem Klassen-Wechsel.
2. Design-Tokens als Fundament
Design-Tokens sind die kleinste Einheit eines Design-Systems. In einem Multi-Brand-Theming-System sind sie der einzige Ort, an dem Markeninformationen gespeichert werden. Alle anderen Teile des Systems – Komponenten, Layouts, Typografie – referenzieren ausschließlich Token, nie direkte Farbwerte. Die Token-Hierarchie im Tailwind CSS Multi-Brand-Theming hat typischerweise drei Ebenen: Primitive Tokens (echte Werte wie #0ea5e9), Semantic Tokens (Bedeutung wie --color-action) und Component Tokens (Kontext wie --btn-primary-bg).
Für ein echtes Multi-Brand-Theming-System mit Tailwind reichen Semantic Tokens in den meisten Fällen aus. Component Tokens werden nur dann eingeführt, wenn eine Komponente markenspezifisch so stark abweicht, dass semantische Token nicht ausreichen. Das Token-System sollte in einer eigenen CSS-Datei (z.B. tokens.css) definiert werden, die alle Marken-Overrides enthält. Diese Datei wird von der CI/CD-Pipeline aus einer zentralen Token-Quelle (z.B. einem Design-Token-JSON aus Figma Tokens Plugin) generiert.
/* tokens.css — generated from design token source of truth */
/* === Primitive tokens (shared across all brands) === */
:root {
--primitive-sky-500: #0ea5e9;
--primitive-sky-700: #0369a1;
--primitive-emerald-500: #10b981;
--primitive-rose-500: #f43f5e;
--primitive-slate-900: #0f172a;
}
/* === Brand A: Mironsoft (default) === */
[data-brand="mironsoft"], :root {
--color-brand-primary: var(--primitive-sky-500);
--color-brand-primary-dark: var(--primitive-sky-700);
--color-brand-success: var(--primitive-emerald-500);
--color-brand-danger: var(--primitive-rose-500);
--font-brand-heading: 'Inter', sans-serif;
--radius-brand-card: 1rem;
}
/* === Brand B: Acme Corp === */
[data-brand="acme"] {
--color-brand-primary: #7c3aed;
--color-brand-primary-dark: #5b21b6;
--color-brand-success: #059669;
--color-brand-danger: #dc2626;
--font-brand-heading: 'Poppins', sans-serif;
--radius-brand-card: 0.5rem;
}
/* === Brand C: Greentech === */
[data-brand="greentech"] {
--color-brand-primary: #16a34a;
--color-brand-primary-dark: #15803d;
--color-brand-success: #0d9488;
--color-brand-danger: #b45309;
--font-brand-heading: 'Nunito', sans-serif;
--radius-brand-card: 1.5rem;
}
3. @theme in Tailwind CSS v4 für Brand-Token
In Tailwind CSS v4 werden Design-Tokens über die @theme-Direktive mit dem Tailwind-Utility-System verknüpft. Der Trick für Multi-Brand-Theming: @theme referenziert CSS Custom Properties, die in der Token-Datei definiert werden. Tailwind generiert aus diesen Referenzen Utility-Klassen. Wenn die Custom Properties über einen Theme-Selektor geändert werden, ändern sich automatisch die Werte aller Utilities, die diese Properties referenzieren – ohne dass ein erneuter Build nötig ist.
Das ermöglicht Runtime-Theme-Switching: Der Nutzer wählt eine Marke, ein data-brand-Attribut wird gesetzt, CSS Custom Properties wechseln sofort, alle Tailwind-Klassen zeigen die neue Marke. Dieses Muster setzt voraus, dass alle markenspezifischen Token als CSS Custom Properties definiert sind und Tailwind's @theme nur auf diese Properties verweist. Die Utilities bg-brand-primary, text-brand-primary und ring-brand-primary existieren nur einmal im CSS, zeigen aber für jede Marke die richtigen Werte.
4. CSS Custom Properties als Theming-Layer
CSS Custom Properties sind das Fundament für jedes ernstzunehmende Tailwind CSS Multi-Brand-Theming-System. Sie sind die einzige native CSS-Technik, die es erlaubt, Werte zur Laufzeit zu ändern, ohne CSS neu zu laden oder zu berechnen. Jede CSS Custom Property kann durch einen Selektor mit höherer Spezifizität überschrieben werden – genau das nutzt das Multi-Brand-Theming-Muster. Der Root-Selektor definiert die Standard-Marke, jeder Marken-Selektor überschreibt die Token.
Der wichtige Unterschied zu Tailwind-Klassen: Custom Properties kaskadieren. Ein --color-brand-primary auf einem Elternelement gilt für alle Kindelemente, bis es überschrieben wird. Das macht es möglich, innerhalb einer einzigen Seite mehrere Marken zu zeigen – zum Beispiel in einer Preview-Ansicht eines Editors oder in einem Vergleichs-Dashboard. Für diesen Use Case würden Klassen-basierte Theming-Systeme komplexe Logik brauchen, während Custom Properties das von Natur aus unterstützen.
5. data-Attribute für Theme-Switching
Das data-brand-Attribut auf dem html- oder body-Element ist die sauberste Methode für Multi-Brand-Theming. Es macht den aktiven Brand im HTML-Markup lesbar, erlaubt CSS-Selektoren wie [data-brand="acme"] und vermeidet Klassen-Kollisionen mit Tailwind. Der Wechsel im JavaScript ist ein einzelner Attribut-Set-Aufruf, der sofort alle CSS Custom Properties und damit alle Tailwind-Utilities aktualisiert. Kein Re-render, kein State-Management, kein erneuter API-Call.
In Magento 2 mit Hyvä Themes wird das data-brand-Attribut idealerweise serverseitig gerendert: Das PHP-Template liest die Marke aus der Store-Konfiguration und setzt das Attribut beim Page-Render. Für dynamisches Switching ohne Page-Reload – z.B. in einem Konfigurator – übernimmt Alpine.js das Setzen des Attributs. Das Multi-Brand-Theming-System bleibt unabhängig davon funktional, weil die gesamte Styling-Logik in CSS Custom Properties liegt und kein JavaScript für das Rendering der richtigen Farben nötig ist.
<!-- Server-rendered: brand set on html element -->
<html lang="de" data-brand="acme">
<!-- Alpine.js brand switcher component -->
<div
x-data="{
currentBrand: localStorage.getItem('brand') || 'mironsoft',
brands: ['mironsoft', 'acme', 'greentech'],
switchBrand(brand) {
this.currentBrand = brand;
document.documentElement.setAttribute('data-brand', brand);
localStorage.setItem('brand', brand);
},
init() {
// Apply stored brand on page load
document.documentElement.setAttribute('data-brand', this.currentBrand);
}
}"
class="flex gap-2"
>
<template x-for="brand in brands" :key="brand">
<button
@click="switchBrand(brand)"
:class="currentBrand === brand
? 'bg-brand-primary text-white'
: 'bg-white text-slate-700 border border-slate-200'"
class="px-4 py-2 rounded-lg text-sm font-semibold transition-colors"
x-text="brand"
></button>
</template>
</div>
<!-- Tailwind classes using brand tokens — same classes, different values per brand -->
<section class="bg-brand-primary text-white p-8 rounded-[--radius-brand-card]">
<h1 class="font-bold text-2xl">Brand headline</h1>
<button class="bg-white text-brand-primary px-6 py-3 rounded-lg font-semibold mt-4">
Call to action
</button>
</section>
6. Dark Mode im Multi-Brand-Kontext
Dark Mode und Multi-Brand-Theming kombinieren zu müssen, ist die Königsdisziplin im Tailwind-Theming. Die naive Lösung – für jede Marke × Dark-Mode-Kombination einen Selektor schreiben – erzeugt quadratisch wachsende CSS-Komplexität. Das elegante Muster für Multi-Brand-Theming mit Dark Mode nutzt zwei Attribute-Selektoren kombiniert: [data-brand="acme"][data-theme="dark"] überschreibt nur die Token, die im Dark Mode anders aussehen sollen, während alle anderen Token von der Brand-Definition geerbt werden.
Tailwind CSS v4 unterstützt Dark Mode über das dark:-Präfix, das auf die CSS-Klasse .dark oder – in v4 – auf ein konfigurierbares Attribut reagiert. Für Multi-Brand-Theming empfiehlt sich die Kombination von data-brand für Marken und data-theme="dark" für den Dark Mode, weil so beide Dimensionen unabhängig voneinander geschaltet werden können. Die CSS Custom Properties für Dark Mode überschreiben nur die visuellen Token (Farben, Hintergründe), während strukturelle Token (Radien, Typografie) markenspezifisch bleiben.
7. Build-Pipeline für mehrere Brands
In Tailwind v3 war es üblich, für jede Marke einen separaten Build mit einer eigenen tailwind.config.js auszuführen. Das erzeugte mehrere CSS-Dateien mit duplizierten Utility-Klassen und nur unterschiedlichen Werten. In Tailwind v4 mit CSS Custom Properties entfällt dieser Ansatz komplett: Es gibt eine einzige CSS-Ausgabedatei, die alle Marken-Token enthält. Der Build läuft einmal, das Ergebnis bedient alle Marken.
Für sehr große Multi-Brand-Theming-Projekte mit hunderten von Marken empfiehlt sich ein Token-Generierungsskript, das eine einzige CSS-Datei mit allen Marken-Selektoren aus einer JSON-Quelldatei erstellt. Diese JSON-Datei ist die einzige Stelle, die bei einer neuen Marke bearbeitet wird. Das Build-Skript liest die JSON, generiert die CSS Custom Property-Blöcke und gibt sie in die Token-CSS-Datei aus. Tailwind verarbeitet diese Datei transparent – es "weiß" nichts von den Marken, es kennt nur die Utility-Klassen, die aus @theme generiert wurden.
8. Ansätze im direkten Vergleich
Es gibt mehrere Wege, Multi-Brand-Theming in Tailwind umzusetzen. Die folgende Tabelle zeigt die wichtigsten Ansätze und ihre Eignung für reale Projekte.
| Ansatz | Wie es funktioniert | Vorteile | Nachteile |
|---|---|---|---|
| Separate Configs (v3) | Eine tailwind.config.js pro Marke, separate Builds | Vollständige Trennung | Mehrere Builds, CSS-Duplikation |
| CSS Custom Properties | Ein Build, Token via data-Attribut wechselbar | Runtime-Switching, ein Build | Nur Wert-Tokens, keine Klassen-Änderungen |
| Klassen-Override | Marken-Klassen in Templates per Condition setzen | Einfach zu verstehen | Wächst exponentiell mit Marken-Anzahl |
| @theme + Custom Properties | Tailwind v4: Token in @theme, Werte via CSS Props | Best of both worlds | Erfordert Tailwind v4 |
9. Theme-Testing und visuelle Regressionstests
Ein Multi-Brand-Theming-System ist nur so gut wie seine Tests. Visuelle Regressionstests mit Playwright oder Cypress können für jede Marke separate Screenshot-Snapshots erstellen und bei Pull Requests vergleichen. Das Muster: Für jeden Test wird das data-brand-Attribut programmatisch gesetzt, ein Screenshot wird erstellt und mit dem gespeicherten Baseline-Screenshot verglichen. Wenn ein Design-Token geändert wird, schlagen alle Tests der Marken fehl, die diesen Token verwenden – das ist gewolltes Verhalten.
Für Storybook-basierte Komponenten-Bibliotheken ermöglicht das Multi-Brand-Theming eine elegante Story-Struktur: Eine Story, mehrere Brand-Decorators. Jeder Decorator setzt data-brand auf dem Wrapper-Element. Chromatic rendert alle Varianten und vergleicht sie. Das ersetzt dozens von duplizierten Stories durch eine einzige Story mit mehreren Brand-Varianten. Der Aufwand für das Hinzufügen einer neuen Marke reduziert sich auf das Erstellen der Token-CSS und das Hinzufügen des Brands zur Decorator-Liste.
/* main.css — single file for all brands in Tailwind v4 */
@import "tailwindcss";
@import "./tokens.css";
@theme {
/* Map CSS Custom Properties to Tailwind utilities */
--color-brand-primary: var(--color-brand-primary);
--color-brand-primary-dark: var(--color-brand-primary-dark);
--color-brand-success: var(--color-brand-success);
--color-brand-danger: var(--color-brand-danger);
/* Structural tokens — brand-specific radius and typography */
--radius-brand-card: var(--radius-brand-card);
--font-family-brand: var(--font-brand-heading);
}
/* Utility classes for dark mode — works across all brands */
@utility bg-brand-surface {
background-color: var(--color-brand-primary);
@media (prefers-color-scheme: dark) {
background-color: var(--color-brand-primary-dark);
}
}
/* Brand-aware focus ring — changes color per active brand */
@utility focus-brand {
&:focus-visible {
outline: 2px solid var(--color-brand-primary);
outline-offset: 2px;
}
}
10. Zusammenfassung
Tailwind CSS Multi-Brand-Theming mit CSS Custom Properties und Tailwind v4 ist das robusteste Muster für Projekte, die mehrere Marken aus einem Codebase bedienen müssen. Die Architektur ist klar: Semantic Design-Tokens als CSS Custom Properties, @theme für die Verknüpfung mit Tailwind-Utilities, data-brand-Attribute für das Switching. Eine einzige CSS-Ausgabedatei bedient alle Marken. Runtime-Switching ohne Page-Reload ist möglich. Neue Marken werden durch das Hinzufügen eines Token-Blocks eingeführt, ohne Template-Änderungen.
Der wichtigste Grundsatz bei der Implementierung: Niemals direkte Farbwerte in Tailwind-Klassen verwenden, wenn das Projekt mehr als eine Marke hat. Immer semantische Token-Klassen wie bg-brand-primary statt bg-sky-500. Dieser Disziplin konsequent zu folgen, zahlt sich bei jeder neuen Marke aus und macht das Multi-Brand-Theming-System wartbar, testbar und erweiterbar.
Tailwind CSS Multi-Brand-Theming — Das Wichtigste auf einen Blick
Token-Architektur
Semantic Design-Tokens als CSS Custom Properties. Primitive → Semantic → Component. @theme verknüpft Token mit Tailwind-Utilities.
Theme-Switching
data-brand Attribut auf html-Element. CSS-Selektoren überschreiben Token. Runtime-Switching ohne Page-Reload und ohne Re-build.
Build-Effizienz
Ein einziger Tailwind-Build für alle Marken. Keine CSS-Duplikation. Neue Marken durch Token-Block, keine Template-Änderungen nötig.
Testing
Playwright/Cypress setzen data-brand programmatisch. Screenshots für jede Marke. Eine Story, mehrere Brand-Decorators in Storybook.