OKLCH in Tailwind v4
Tailwind v4 hat seine Standard-Farbpalette in OKLCH neu aufgebaut und die
Konfiguration in CSS selbst verlagert: Eigene Farben sind jetzt schlichte CSS
Custom Properties, geschrieben in oklch() und unter der @theme-Direktive
deklariert statt in tailwind.config.js. Die neu aufgebaute Palette stuft
gleichmäßiger und erreicht die zusätzliche Leuchtkraft von P3-Displays mit
großem Farbraum — und beide Eigenschaften stehen auch deinen eigenen
Markenfarben offen, wenn du die Farbrampe so aufbaust, wie die Standardpalette
aufgebaut wurde.
Genau darum geht es hier eigentlich: nicht darum, Tailwinds Farben zu benutzen, sondern eine eigene Palette dazu zu bringen, sich genauso zu verhalten. Das Farbmodell, das die eigentliche Arbeit leistet, hat seine eigene Reihe in unserem OKLCH-Leitfaden.
Was hat sich bei Farbe in Tailwind v4 geändert?
Zwei Umstellungen kamen gleichzeitig.
Die Standardpalette wurde in OKLCH neu erzeugt. Öffne die
Farbreferenz in den Tailwind-Docs
und die Werte sind oklch()-Strings statt hex. Die praktischen Effekte:
Die Schritte innerhalb jeder Skala sind perzeptiv gleichmäßiger, und auf
Display-P3-Bildschirmen tragen die Mitteltöne Chroma, das sRGB-hex nicht
ausdrücken konnte — die Palette wirkt auf den meisten aktuellen Handys und
Laptops kräftiger, ohne dass sich ein Klassenname ändert.
Die Konfiguration wurde CSS-first. Die @theme-Direktive ersetzt einen
Großteil von tailwind.config.js: Design Tokens sind CSS Custom Properties,
die in deinem Stylesheet deklariert werden, und Tailwind erzeugt daraus die
Utilities. Farben leben im --color-*-Namespace. Eine Konsequenz, die man
bemerken sollte, bevor irgendeine Farbtheorie ins Spiel kommt: Deine Palette
liegt jetzt in derselben Datei und Sprache wie der Rest deines CSS — lesbar
und direkt an Ort und Stelle editierbar.
Wie definierst du eigene Markenfarben in @theme?
Deklariere Eigenschaften mit dem Namen --color-<name>-<step>, und die
Utilities folgen daraus:
@import "tailwindcss";
@theme {
--color-brand-100: oklch(0.93 0.03 262.9);
--color-brand-300: oklch(0.78 0.10 262.9);
--color-brand-500: oklch(0.60 0.19 262.9);
--color-brand-600: oklch(0.546 0.215 262.9); /* #2563eb */
--color-brand-700: oklch(0.49 0.19 262.9);
--color-brand-900: oklch(0.36 0.12 262.9);
}
Mit diesem Block an Ort und Stelle funktionieren bg-brand-600,
text-brand-100, border-brand-300 und jede andere Farb-Utility genau so
wie bei der eingebauten Palette.
Diese Werte sind ein durchgerechnetes Beispiel, kein Füllmaterial. Der Schritt
600 ist die Ausgangsfarbe: oklch(0.546 0.215 262.9) ist exakt #2563eb, das
Blau, das Tailwind v3 als blue-600 auslieferte. Die anderen fünf wurden
daraus erzeugt — der Farbton bei 262,9 über die ganze Rampe gehalten, die
Helligkeit entlang einer Kurve geführt, das Chroma folgt einem Glockenprofil,
das nahe der Ausgangsfarbe seinen Höhepunkt hat und zu beiden Enden hin
ausläuft. Ihre hex-Zwillinge landen bei ≈ #dde8fd, #95b7f8, #3f78f0,
#2055ca und #19387b.
Was bringt dir OKLCH gegenüber dem Einfügen von hex-Codes?
Die Rampe verhält sich wie Tailwinds eigene. Die Standard-Skalen wirken
gleichmäßig, weil sie auf einem perzeptiven Modell
erzeugt wurden; eine von Hand zusammengesetzte hex-Markenskala war es meist
nicht und sitzt deshalb im selben Projekt mit anderer Physik — der Sprung von
brand-500 zu brand-600 hat eine andere Größe als derselbe Sprung in
gray, Hover-Ableitungen landen ungleichmäßig, und der Kontrast muss Paar für
Paar getestet werden, statt sich aus der Helligkeitsspalte ablesen zu lassen.
Eine in OKLCH erzeugte Marken-Rampe erbt die Eigenschaften, für die die
Standardpalette neu aufgebaut wurde: gleichmäßige Schritte und einen Kontrast,
den du aus den L-Werten vorhersagen kannst.
Die Werte antworten auch. #2563eb und #2055ca sagen dir nichts darüber,
wie sie zusammenhängen; oklch(0.546 0.215 262.9) und oklch(0.49 0.19 262.9)
sagen es dir genau — gleicher Farbton, eine Stufe dunkler, etwas weniger
farbig. Das ist der intuitive Grund, warum OKLCH in eine Theme-Datei gehört:
Die Zahlen entsprechen endlich der Art, wie Designer Farbe ohnehin
untereinander beschreiben — „gleich, nur dunkler“ — und deshalb wird direktes
Editieren an Ort und Stelle sinnvoll. Wenn brand-600 zu schwer wirkt, erhöhe
sein L um 0,02, und du weißt genau, was du geändert hast.
Öffne diese Marken-Rampe mit ihrem Tailwind-Export in Scale Composer
— die Skala von oben, erzeugt aus der Ausgangsfarbe #2563eb, mit dem
@theme-Block, der im Export-Panel zusammengesetzt wird, und hex neben jedem
Schritt.

Wie sieht der Erzeugen-und-Einfügen-Workflow aus?
Drei Schritte, keiner davon Feintuning von Hand:
- Ausgangsfarbe. Füge die Markenfarbe ein — hex ist in Ordnung; sie wird in OKLCH-Koordinaten umgerechnet, und die Rampe wird darum herum erzeugt: Schritte auf einer Helligkeitskurve, ein Glocken-Chromaprofil mit einem Boden, damit die blassesten Schritte einen Hauch des Farbtons behalten, und Chroma leicht unter der Farbraum-Obergrenze gedeckelt, damit kein Schritt abgeschnitten wird. Eine Dark-Mode-Variante lässt sich aus derselben Rampe mit einer eigenen Helligkeitskurve und einem Chroma-Boost ableiten.
- Prüfen. Kontrast-Untergrenzen werden pro Rolle bewertet (WCAG, mit APCA daneben), sodass die Schritte, die du für Text und Hintergründe vorsiehst, geprüft sind, bevor irgendetwas exportiert wird.
- Export. Der Tailwind-v4-Export ist ein einziger
@theme-Block — die Farbrampen plus, wenn du sie willst, Schriftgrößen-Stufen, Abstände, Radien und Breakpoints im selben Dialekt. Füge ihn in dein Stylesheet ein, und die Utilities existieren.
Ändert OKLCH, wie Utilities funktionieren?
Nein — und das sollte man klar sagen. bg-brand-600 verhält sich identisch,
egal ob die zugrunde liegende Eigenschaft einen oklch()-Wert oder einen
hex-Code hält; Klassennamen, Varianten und die Build-Pipeline sind gleichgültig
gegenüber der Notation. OKLCH ändert die Qualität der Werte — gleichmäßige
Schritte, direkte Editierbarkeit, P3-Reichweite — nicht die API. Das heißt
auch: Die Migration kann schrittweise erfolgen — neue Tokens lassen sich in
oklch() schreiben, während bestehende hex-Tokens unberührt bleiben, bis du
einen Grund hast, sie neu zu erzeugen.
Natives oklch() ist seit 2023 in allen großen Browsern verfügbar,
sodass für aktuelle Zielplattformen keine Build-Transformation nötig ist.
Was ist der schnellste Weg, es mit deiner eigenen Marke auszuprobieren?
Die Beispiel-Rampe oben ist die Ausgabe einer einzigen Ausgangsfarbe; der
Workflow ist für jede Farbe derselbe. Wirf deine eigene Markenfarbe als
Ausgangsfarbe hinein — sie wird in OKLCH umgerechnet, die Rampe
wird nach denselben Regeln erzeugt wie das Beispiel, und der @theme-Block im
Export-Panel ist bereit zum Einfügen.