Farbe/Relative Farbangaben

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche

Bisher arbeitete man in CSS hauptsächlich mit festen Farbwerten wie #09c, rgb(224 61 144) oder hsl(200 30% 40%).
Wenn man eine dunklere oder hellere Variante brauchte, musste man diese außerhalb von CSS berechnen — mit einem Grafikprogramm oder einem Color Picker.

Diese festen Farbwerte sind allerdings isoliert:

  • sie stehen für sich,
  • sie enthalten keine Information darüber, wie sie verändert werden könnten,
  • und jede neue Abstufung muss als eigener Wert eingetragen werden.

Genau das führt zu sogenannten Magic Numbers:
Werte, die aus dem Nichts kommen und deren Herkunft oder Logik nicht mehr nachvollziehbar ist.

.button {
  background: #3a7bd5; /* Warum genau dieser Wert? */
}
.button:hover {
  background: #2a6bb8; /* Und warum genau dieser? */
}

Wer den Code später liest, weiß nicht mehr:

  • Wie kam man auf die Hover-Farbe?
  • Ist es 10% dunkler? 20%?
  • Oder einfach ein zufällig passender Farbton?

Relative Farbwerte lösen genau dieses Problem: Mit dem CSS Color Module Level 5[1] kannst du Farben direkt im CSS ableiten – ohne Grafikprogramm, ohne neue Magic Numbers. Dieses Tutorial zeigt, wie man anhand eines Farbwerts mit neuen CSS-Funktionen weitere Akzente und Komplementärfarben mit hohem Kontrast automatisch erzeugt.


Eine Farbpalette automatisch erzeugen

Bisher mussten alle Farben einer Farbpalette in einem Grafikprogramm berechnet und festgelegt werden. So kamen für eine Grund- und mehrere Akzentfarben schnell viele Farbwerte zusammen.

Mit der relativen Farbsyntax[2] können Grund- und Akzentfarben in einem beliebigen Farbraum oder einer beliebigen Syntax und entsprechende Varianten mit viel weniger Code erstellt werden.[3] Die Ausgangsfarbe wird als Grundlage verwendet, um Schritt für Schritt neue Töne und Schattierungen zu erzeugen.

Achtung!

Die Beispiele in diesem Tutorial funktionieren (Stand: Dezember 2025) in allen modernen Browsern!
Farben außerhalb des RGB-Farbraums werden in einigen hochwertigen Geräten wie iPhones ab 2017 angezeigt, sonst in vergleichbaren Farben im kleineren RGB-Farbraum dargestellt.

Für ältere Browser gibt es einen Polyfill von Evil Martians, alternativ müsste man die errechneten Farbwerte einmal manuell in HEX-Werte umrechnen.

--Matthias Scharwies (Diskussion) 13:11, 1. Dezember 2025 (CET)

Schlüsselwort from

In Level 5 der Color-Spezifikation wurden alle Farbfunktionen um die Möglichkeit erweitert, Farben relativ zu einer Bezugsfarbe angeben zu können. Dazu notiert man das Schlüsselwort from, die Bezugsfarbe und dann die Farbwerte. Diese Farbanteile werden durch die Buchstaben repräsentiert, die das jeweilige Farbmodell verwendet, der Transparenzwert der Bezugsfarbe kann mit dem Schlüsselwort alpha einbezogen werden.

In diesem Beispiel aus der Spec wird eine Farbe um eine durchscheinende Variante für ein Overlay erweitert:

:root { --bg-color: blue; }
.overlay {
  background: rgb(from var(--bg-color) r g b / 20%);
}
var(--bg-color)
rgb(from var(--bg-color) r g b / 20%)

Als Standard-Hintergrundfarbe wird Blau in der custom property --bg-color:blue festgelegt.

Für die Klasse overlay wird nun eine rgb()-Funktion aufgerufen, die über das Schlüsselwort from die entsprechende Farbfestlegung aufnimmt. Die r-, g- und b-Kanäle der Ursprungsfarbe bleiben unverändert, indem sie mit den Schlüsselwörtern angegeben werden, die ihre Werte von der Ursprungsfarbe ableiten. Zusätzlich wird aber die Deckkraft auf 20% gesetzt, um sie transparent zu machen, unabhängig davon, wie hoch die Deckkraft der Ursprungsfarbe war.

Beachte: Die Bezugsfarbe kann in einem beliebigen Farbmodell angegeben sein, CSS rechnet das passend um. Das kann natürlich zu Genauigkeitsverlusten führen: wenn man eine OKLCH-Farbe, die außerhalb des SRGB-Farbraums liegt, als Bezugsfarbe in der rgb()-Funktion verwendet, entsteht bei der Umrechnung eine möglichst gut passende Ersatzfarbe.

Das Problem von durchscheinenden Farbtönen ist die Abhängigkeit vom Hintergrund. Der oben gezeigte Farbwert ist auf weißem Hintergrund pastellblau – im Dark Mode jedoch ein sehr dunkles mitternachtsblau.

Farbabstufungen in hell und dunkel

Nehmen wir an, du möchtest zu einer Grundfarbe sowohl eine leuchtende Füllfarbe als auch eine abgedunkelte Umrissfarbe haben. Das musste früher manuell geschehen, jetzt kannst du dies mit Hilfe einer relativen Farbangabe errechnen.

Die Besonderheit ist, dass man für diese Farbwerte die calc()-Funktion verwenden kann, um aus den Farbanteilen der Bezugsfarbe neue Farben zu errechnen.

Automatische Abstufungen So sieht's aus
:root {
  --background:  #ddd;
  --base: blue;
  --base-light-1: oklch(from var(--base) calc(l + 0.25) c h);
  --base-light-2: oklch(from var(--base) calc(l + 0.5 ) c h);

  --base-dark-1: oklch(from var(--base) calc(l - 0.25) c h);
  --base-dark-2: oklch(from var(--base) calc(l - 0.5 ) c h);
}
var(--base)
oklch(from var(--base) calc(l + 0.5 ) c h)
oklch(from var(--base) calc(l + 0.25) c h)
oklch(from var(--base) calc(l - 0.25) c h)
oklch(from var(--base) calc(l - 0.5 ) c h)

In diesem Beispiel wird erst eine Grundfarbe definiert.

Anschließend werden weitere custom properties angelegt, für die wir die Farbwerte l (Luminanz), c (Chroma) und h (Farbton) des LCH-Farbmodells verwenden.

Mit dem Schlüsselwort from rufen wir die Grundfarbe auf und addieren, bzw. subtrahieren den Wert für die Helligkeit um 0.25 , bzw. 0.5, ohne irgendeinen anderen Aspekt der Farbe zu verändern. Die Grundfarbe ist zwar als Farbname (also sRGB) angegeben, das wird von CSS aber automatisch in das Farbmodell der genutzten Farbfunktion umgerechnet.

Empfehlung:
Ändere den Wert für --base in den Entwickler-Werkzeugen deines Browsers.
Was passiert, wenn du die Grundfarbe auf gelb änderst?

Die Lösung wird in einem späteren Abschnitt gezeigt!

Akzentfarben

Oftmals ergibt sich auch der Wunsch, den Ton einer Farbe abzuändern, Sättigung und Helligkeit aber beizubehalten. Auch hierfür können wir das Polarkoordinatenmodell des OKLCH-Farbraums nutzen.


Hue-Rad
60°
120°
240°
300°
180°


Automatische Akzentfarben So sieht's aus
:root {
  --base: blue;
  --accent-warm: oklch(from var(--base) l c calc(h + 20));	
  --accent-cool: oklch(from var(--base) l c calc(h - 20));
  --accent-complement: oklch(from var(--base) l c calc(h + 180));	
  --accent-complement-light-2: oklch(from var(--base) calc(l + 0.5 ) c calc(h + 180));			
}
var(--base)
oklch(from var(--base) l c calc(h + 20))
oklch(from var(--base) l c calc(h - 20))


oklch(from var(--base) l c calc(h + 180))
oklch(from var(--base) calc(l + 0.25 ) c calc(h + 180))
oklch(from var(--base) calc(l + 0.5 ) c calc(h + 180))

Wenn du zu einer Farbe die Komplementärfarbe errechnen willst, geht das ganz einfach, indem du 180 auf den h-Wert aufaddierst. Die Farbtonwerte der diversen Polarkoordinatenmodelle folgen dem gebräuchlichen Farbkreis. Für diesen Farbton werden nun einige Helligkeitsvarianten angelegt.

Alternativ könnte man eine triadische Kombination erstellen:

var(--base)
oklch(from var(--base) l c calc(h + 120))
oklch(from var(--base) l c calc(h - 120))

Beim Einsatz solcher Farben sollte aber immer Wert auf hohe Kontraste und gute Lesbarkeit gelegt werden.

Farben und Kontraste

Textfarben mit hohem Kontrast

Früher musst man im nächsten Schritt zu jeder Hintergrundfarbe passende Schriftfarben suchen und dann den Kontrast testen. Jetzt schafft dies CSS ganz alleine:

Alle Grundfarben unserer Palette haben die gleiche wahrgenommene Helligkeit.

Im folgenden Beispiel werden für dunkle Farbtöne helle Schriftfarben, für helle Hintergründe entsprechend dunklere Varienten erzeugt:[4]

kontrastreiche Schriftfarben mit relativer Farbsyntax So sieht's aus
aside {
  color:      var(--tone);
  background-color: oklch(from var(--tone) calc(l + 45) calc(c * 0.5) h);
  box-shadow: 0.3em 0.6em 1em 
              color-mix(in oklch, var(--tone) 90%, black 10%);;
 
	h2 {
		background-color: var(--tone);
		color:            oklch(from var(--tone) calc(l + 40) c h);
	}
}

.info {
	--tone: var(--color-primary);
}

.warning {
	--tone: var(--color-secondary);
}
.success {
	--tone: var(--color-tertiary);
}
Beachte: Wichtiges wie Fehlermeldungen sollte nicht alleine durch Farben gekennzeichnet werden!

color-mix() als Fallback

Nutzer älterer Browser sehen bei den oben gezeigten Farbfeldern mit relativen Farbangaben nur weiße Kästchen.

Mit der color-mix()-Funktion kann man dies umgehen:

color-mix(method, color1[ p1], color2[ p2])

Das Schlüsselwort in leitet einen Farbraum ein, in dem die Farbmischung erzeugt werden soll.

Danach folgen zwei Farbangaben, optional ergänzt durch eine Prozentangabe:

color-mix(in oklch, red, yellow)
color-mix(in oklch, red 30%, blue )
color-mix(in srgb, #337599 80%, white)
color-mix(in oklch longer hue, #337599 60%, white)


[5]

Farbkreis in oklch() So sieht's aus

Farbinterpolation

Zwischen zwei Farben einen Übergang zu ermitteln – zu interpolieren – ist eine Aufgabe, die CSS an verschiedenen Stellen lösen muss.

Das CSS Farbenmodul Level 4 definiert eine allgemeine Syntax, um den bei der Farbinterpolation zu verwendenden Farbmodell festlegen zu können. Eine solche Interpolationsangabe wird durch das Schlüsselwort in eingeleitet, gefolgt von dem konkreten Farbkoordinatensystem, das verwendet werden soll. Bei den Systemen, die auf Polarkoordinaten basieren, kann zusätzlich die Richtung angegeben werden, um die der Farbwert gedreht werden soll.

Syntax

  in <system> [ <richtung> hue ]

Bei in und hue handelt es sich um Schlüsselwörter. Als <system> ist eins der nachfolgend aufgelisteten Koordinatensysteme zu verwenden. Die möglichen Werte für <richtung> finden sich bei den Polarkoordinatensystemen.

Rechtwinklige Koordinatensysteme

Die Koordinaten in diesen Darstellungen haben in jeder Dimension zwei klar definierte, entgegengesetzte Enden.

srgb
Das ursprünglich verwendete Verfahren ist eine lineare Interpolation im sRGB-Farbraum. Diese Interpolation ist einfach realisierbar, aber der sRGB Farbraum ist nicht auf gleichförmige Ausleuchtung oder gleichmäßige Wahrnehmbarkeit ausgelegt, sondern auf einfache technische Darstellung auf einem Monitor. Deshalb sind sRGB-Farbverläufe oft zu dunkel oder zu sehr grau.
srgb-linear
xyz
xyz-d50
xyz-d65
Diese Farbräume haben eine lineare Lichtintensität und führen zu einem Ergebnis, das der Mischung farbigen Lichts entspricht. xyz steht für den XYZ-Farbraum im CIE Normvalenzsystem, von dem die übrigen CIE-Farbräume wie Lab oder LCH abgeleitet sind.
lab
oklab
L*a*b ist eine verständlichere Darstellung des CIE Normfarbraumes, basierend auf L (Helligkeit) und einer Positionierung auf den Komplementärfarbskalen grün/rot sowie blau/gelb. Der L*a*b Farbraum soll besser der menschlichen Wahrnehmung entsprechen, macht aber Schwierigkeiten bei der Bildverarbeitung, weshalb von Björn Ottoson eine verbesserte Umrechnung von XYZ in Lab vorgeschlagen wurde, die beim W3C Anklang fand. Dieses bessere Lab ist "okay", deshalb nannte man es oklab. In einer Farbinterpolation haben lab und oklab den Vorteil, dass der wahrgenommene Farbübergang gleichmäßiger ist.

Polare Koordinatensysteme

In einem polaren Koordinatensystem ist eine Achse kreisförmig, d.h. ihr Ende geht nahtlos wieder in den Anfang über

hsl
hwb
Das System HSL (Hue - Saturation - Lightness = Farbton - Sättigung - Helligkeit) verwendet ein Farbenrad für den Farbton und leitet die übrigen Farben als Farbsättigung (0%=Grau, 100%=Vollton) und Helligkeit (von 0=Schwarz, 50%=Vollfarbe und 100%=Weiß) daraus ab. Das HWB System (Hue - Whiteness - Blackness) arbeitet ähnlich. Der Vorteil dieser Systeme ist, dass sie Menschen verständlicher sein sollen als RGB-Farbangaben. Bei einer Interpolation kann man Farbübergänge als Wechsel zwischen den Farbtönen darstellen. Das führt bei einem Übergang rot nach blau aber auch zu ganz anderen Farben, die eher ein Spektrum als einen Farbübergang bilden.
lch
oklch
Der LCH Farbraum ist eine auf Polarkoordinaten umgerechnete Version des L*a*b-Farbraums und basiert auf Helligkeit (L=Luminanz), Farbsättigung (C=Chroma) und Farbton (H=Hue). Der Farbton ist dabei der, der auch im HSL-System genutzt wird. LCH gilt ebenfalls als gleichförmig in der Wahrnehmung, und soll bei Farbinterpolationen das „Ausgrauen“ der Farben vermeiden.

Interpolationsrichtung des Farbtons

In einem polaren Koordinatensystem stellt sich die Frage, in welcher Richtung man sich bei einer Interpolation des Farbtons um den Mittelpunkt des Farbrades drehen möchte. Der Übergang von H=100° zu H=200° kann aus der Folge 100, 101, 102, ... 199, 200 bestehen, aber auch aus der Folge 100, 99, ..., 1, 0, 359, 358, ... 201, 200.

Standardmäßig verwendet CSS den kleineren möglichen Drehwinkel. Das entspricht der Richtungsangabe shorter in der Farbinterpolationsangabe. Den größeren Drehwinkel spezifiziert man mit der Angabe longer.

Darüber hinaus gibt es noch die Angaben increasing (aufsteigend) und decreasing (absteigend), damit gibt man an, dass man in Richtung auf- oder absteigender Winkelwerte interpolieren möchte, ganz gleich, ob das der größere oder der kleinere Winkel ist.

Vergleichstafel

Die nachfolgende Vergleichstafel zeigt, wie sich die Interpolationsmethode auswirkt (in Arbeit!)

Markup für die Vergleichstafel So sieht's aus
<style>
ul {
   --from: hsl(340, 100%, 50%);
   --to: hsl(130, 100%, 50%);
}
li {
   height: 2em;
   background: linear-gradient(to right var(--hue-scheme), var(--from), var(--to)) right center / 85% 100% no-repeat;
}
</style>

<ul>
  <li style="--hue-scheme: in srgb">SRGB</li>
  ...
  <li style="--hue-scheme: in oklch longer hue">OKLCH longer hue</li>
</ul>


Weblinks

  1. CCSSWG: CSS Color Module Level 5
  2. CCSSWG: Relative Color Syntax (CSS Color Module Level 5)
  3. CSS-Syntax für relative Farben (developer.chrome.com)
  4. Farbe kontrastieren (developer.chrome.com)
  5. Simplify Your Color Palette With CSS Color-Mix() (smashing magazine)