Was macht oklch-Palettformel?
Die neutralen Farben eines Produkts (Seitenhintergrund, Kartenoberflächen, Vertiefungen, Haarspitzen, vier Textstufen) bestehen normalerweise aus 15 bis 30 Hex-Werten pro Theme, die per Auge ausgewählt werden. Sie weichen ab, der Dunkelmodus ist ein zweiter handverlesener Satz, und niemand weiß, welche Paare noch den Kontrast bestehen. Ersetze sie durch eine Formel:
Oberflächenähnlicher Token: L = Papier + Tiefe × n(Token) Chroma = Tönung Farbton = Farbton
Text-Token: L = Tinte + Stufe × n(Token) Chroma = Tinten-Tönung Farbton = Farbton
n(Token) ist die Position des Tokens auf einer Leiter, eine Leiter pro Theme. Verschiebe eine Eingabe, und die gesamte Rampe bewegt sich mit – die Abstände zwischen den Stufen, also der Ort, an dem der Kontrast lebt, bleiben bei einer Umfärbung erhalten. Eine Umfärbung eines Produkts ist eine Zeile (--hue).
Drei Regler (--hue, --lightness, --chroma oder --contrast) steuern jede Farbe.
Dateien
references/palette.css: Einsetzbare Regeln mit Starteingaben und Leitern.scripts/fit_palette.py: Passe Eingaben an eine vorhandene Hex-Palette an und gib ΔE pro Token aus.scripts/ladders.json: Die Standardleitern (hell, dunkel).scripts/palette-audit.mjs: Löse jeden Token in einem echten Browser in beiden Themes auf und schlage bei fehlendem Kontrast Alarm.scripts/oklch.py: Konvertierungen und ΔE / WCAG-Hilfsfunktionen.
Vorgehensweise
-
Benenne die Token nach ihrer Rolle, nicht nach ihrem Wert. Die Standardwerte:
- Hintergründe:
ground(Seite),panel(Schienen, Balken),surface(Karten, Menüs),surface-2(Vertiefungen),surface-3(Chips, hervorgehobene Zeilen),field. - Linien:
line,line-2,line-3(Haarspitzen, hellste bis dunkelste), plusfield-line, der Rand eines Bedienelements, der 3:1 überschreiten muss. - Tinte:
ink,ink-2,ink-3,ink-4(Text, dunkelste bis dezenteste). Jede Tintenstufe ist Text, daher muss jede 4.5:1 überschreiten.
- Hintergründe:
-
Passe an, wähle nicht neu aus. Führe für ein bestehendes Produkt
python3 scripts/fit_palette.py theme.cssaus. Es liest die--color-*Hex-Deklarationen (hell, dann die[data-theme="dark"]-Regel), passt die Eingaben gegen die Standardleiter an und gibt ΔE pro Token aus. Unter 2 ist visuell identisch. -
Überschreibe Leiterstufen, wo das Design sie anders anordnet, niemals die Farbe. Bewerte Kandidaten mit
fit_palette.py theme.css light '<Eingaben>' '<Überschreibungen>', bis das schlimmste ΔE unter ~2 liegt. Typische Überschreibungen:field: 0(Eingabefelder entsprechen der Kartenfläche), ein breiteresline-3, eine größere Lücke zwischeninkundink-2. -
Schreibe die Regeln (siehe
references/palette.css):- Setze die Eingaben und die
--color-*-Formeln auf das Element, das das Theme-Attribut trägt. - Wiederhole jede Eingabe, die du änderst, in der dunklen Regel. Eine für die Standardwerte des Kits geschriebene dunkle Regel würde sonst mit ihren Werten gewinnen.
- Bei Tailwind v4 behalte die Token-Namen in
@theme, damit die Hilfsklassen existieren; die Laufzeit-Deklarationen überschreiben sie.
- Setze die Eingaben und die
-
Prüfe in einem echten Browser:
node scripts/palette-audit.mjs <url>. Es zeichnet jeden Token, liest sRGB zurück und prüft:- jede Tintenstufe bei 4.5:1 gegen jeden Hintergrund;
field-lineundringbei 3:1.
Behebe einen Fehler, indem du die Leiterstufe dieses Tokens verschiebst, nicht indem du eine Farbe gesondert behandelst. Erwarte Fehler bei vorhandenen Paletten: In einer Migration von 17 Apps fand das Audit in mehr als der Hälfte fehlerhafte
ink-4- oderfield-line-Werte, die zuvor ausgeliefert wurden.
Fallstricke
var()innerhalb einer benutzerdefinierten Eigenschaft wird dort aufgelöst, wo sie deklariert ist.- Deklariere die Formeln auf
:rootund setze Eingaben auf einem Kind: Das Kind wird nie neu eingefärbt. - Alias-Token (
--color-heading: var(--color-ink)) müssen ebenfalls auf demselben thematisierten Element deklariert werden.
- Deklariere die Formeln auf
- Tailwind v4
@theme-Werte leben auf:root. Ein auf einen App-Root beschränktes Theme ([data-app]) muss die Formel dort deklarieren, nicht in@theme. - Alles, was Farben an eine Canvas- oder Kartenbibliothek übergibt (
getComputedStyle(...).getPropertyValue('--color-x')) empfängt jetzt einen unaufgelöstenoklch(calc(...))-String. Löse ihn zuerst auf: Zeichne ein Testelement und lies einen 1-Pixel-Canvas aus – genauso wie das Audit es tut. - Ein Farbton für Hintergründe und Tinten. Wenn die Tinten des Designs einen anderen Farbton haben als die Hintergründe, halte
--ink-tintniedrig; bei L 0.98 wirkt jedes Chroma als Farbstich. - Marken-, Status- und Diagrammfarben bleiben außerhalb der Formel. Leite Text-auf-Tönung-Varianten (z. B.
brand-text) vom selben Farbton bei einer festen Helligkeit ab, anstatt sie separat auszuwählen. - Gemischte Farbtöne, nur helle Paletten, die von Kompositionen abgetastet wurden, passen möglicherweise nicht innerhalb von ~2 ΔE. Überspringe sie, anstatt das Design zu verzerren. Das Audit gilt trotzdem.