CSS-Syntax für relative Farben

Neue Farben anhand der Kanäle und Werte einer anderen Farbe erstellen.

Adam Argyle
Adam Argyle

In Chrome 119 gibt es eine sehr leistungsstarke Farbfunktion aus CSS Color Level 5. Die relative Farbsyntax ermöglicht eine einfache Farbmanipulation in CSS und bietet Autoren und Designern folgende Möglichkeiten:

Vor der relativen Farbsyntax mussten Sie zum Ändern der Deckkraft einer Farbe benutzerdefinierte Eigenschaften für die Kanäle einer Farbe erstellen, in der Regel HSL, und sie zu einer endgültigen Farbe und einer endgültigen Variante zusammenstellen. Das bedeutet, dass viele Farbstücke verwaltet werden müssen, was schnell mühsam werden kann.

:root {
  --brand-hue: 300deg;
  --brand-saturation: 75%;
  --brand-lightness: 50%;

  --brand-hsl:
    var(--brand-hue)
    var(--brand-saturation)
    var(--brand-lightness);

  --brand-color: hsl(var(--brand-hsl));

  /* all this work just so I can set the opacity to 50% in a variant */
  --brand-color-variant: hsl(var(--brand-hsl) / 50%);
}

Nach der relativen Farbsyntax können Sie eine Markenfarbe mit einem beliebigen Farbraum oder einer beliebigen Syntax erstellen und eine Variante mit halber Deckkraft mit viel weniger Code erstellen. Außerdem ist es viel einfacher, die Absicht der Stile und des Systems zu erkennen.

:root {
  --brand-color: hsl(300deg 75% 50%);
  --brand-color-variant: hsl(from var(--brand-color) h s l / 50%);
}

In diesem Beitrag erfahren Sie, wie die Syntax funktioniert, und wir zeigen Ihnen einige gängige Farbmanipulationen.

Wenn Sie lieber ein Video ansehen möchten, wird in dieser GUI-Herausforderung fast der gesamte folgende Artikel behandelt.

Syntax Übersicht

Mit der relativen Farbsyntax lässt sich eine Farbe aus einer anderen Farbe ableiten. Die Basisfarbe wird als Ursprungsfarbe bezeichnet. Das ist die Farbe, die nach dem neuen from-Schlüsselwort kommt. Der Browser konvertiert diese ursprüngliche Farbe, zerlegt sie in ihre Bestandteile und bietet diese als Variablen für die neue Farbdefinition an.

Ein Diagramm der Syntax „rgb(from green r g b / alpha)“ wird angezeigt. Ein Pfeil verlässt die Oberseite von „grün“ und biegt in den Anfang der Funktion „rgb“ ab. Dieser Pfeil teilt sich in vier Pfeile, die dann auf die jeweilige Variable verweisen. Die vier Pfeile sind rot, grün, blau und Alpha. Rot und Blau haben den Wert 0, Grün ist 128 und Alpha ist 100%.

Im vorherigen Diagramm wird die ursprüngliche Farbe green in den Farbraum der neuen Farbe konvertiert und in einzelne Zahlen umgewandelt, die als r-, g-, b- und alpha-Variablen dargestellt werden. Diese werden dann direkt als Werte für eine neue rgb()-Farbe verwendet.

Auf diesem Bild sind die Aufschlüsselung, der Prozess und die Variablen zu sehen, die Farbe ändert sich jedoch nicht. Die Variablen werden unverändert in die Farbe zurückgegeben, was weiterhin zu einer grünen Farbe führt.

Das Keyword from

Der erste Teil der Syntax, den Sie lernen müssen, ist from <color>. Sie wird direkt vor der Angabe der Werte eingefügt. Hier ist ein Codebeispiel, in dem nur from green hinzugefügt wurde, direkt vor den Werten für rgb().

.syntax-introduction_same-colors {
  color: green;
  color: rgb(0 128 0);
  color: rgb(from green r g b);    /* result = rgb(0 128 0) */
}

Wenn das Keyword from als erster Parameter in der Funktionsnotation verwendet wird, wird die Farbdefinition in eine relative Farbe umgewandelt. Nach dem Keyword from erwartet CSS eine Farbe, eine Farbe, die die nächste Farbe inspiriert.

Farbkonvertierung

Einfacher ausgedrückt: Es wandelt Grün in die RGB-Kanäle um, um sie in einer neuen Farbe zu verwenden.

rgb(from green r g b)           /* r=0 g=128 b=0 */
rgb(from rgb(0 128 0) r g b);   /* r=0 g=128 b=0 */

Farben aus benutzerdefinierten Properties

rgb from green ist sehr klar und leicht verständlich. Deshalb passen benutzerdefinierte Properties und die relative Farbsyntax so gut zusammen, weil Sie die Farbe von from entschlüsseln können. Sie müssen in der Regel auch nicht das Farbformat der benutzerdefinierten Property-Farbe kennen, da Sie eine neue Farbe in einem beliebigen Format erstellen.

rgb(from rgb(255 105 180) r g b) /* ????? */
rgb(from var(--hotpink) r g b)   /* clear */

Im bevorzugten Farbraum arbeiten

Sie können den Farbraum mit Ihrer Funktionsfarbnotation auswählen.

rgb(from hsl(120 100% 25%) r g b)     /*  r=0   g=128  b=0    */
hsl(from hsl(120 100% 25%) h s l)     /*  h=120 s=100% l=25%  */
hwb(from hsl(120 100% 25%) h w b)     /*  h=120 w=0%   b=50%  */
lch(from hsl(120 100% 25%) l c h)     /*  l=46  c=68   h=134  */

In der Syntax für relative Farben ist dieser Konvertierungsschritt enthalten. Die Farbe nach from wird in den Farbraum umgewandelt, der am Anfang der relativen Farbe angegeben ist. Eingabe und Ausgabe müssen nicht übereinstimmen, was sehr befreiend ist.

Die Möglichkeit, einen Farbraum auszuwählen, ist ebenfalls hilfreich, da die Auswahl eines Farbraums in der Regel eher auf die Art der Farbwechsel als auf eine Präferenz ausgerichtet ist. Die Einstellung ist in den Ergebnissen, nicht im Farbformat oder in den Kanaltypen. Das wird in den Abschnitten mit Anwendungsbeispielen deutlicher, da sich verschiedene Farbräume für verschiedene Aufgaben eignen.

Variablen kombinieren, auslassen und wiederholen

Diese Syntax ist etwas seltsam, aber spannend: Die Variablen müssen nicht in die richtige Reihenfolge gebracht werden und können wiederholt werden.

rgb(from green g g g)    /* rgb(128 128 128) */
rgb(from green b r g)    /* rgb(0 0 128) */
rgb(from green 0 0 g)    /* rgb(0 0 128) */

Deckkraft als Variable

Die Deckkraft wird in der Syntax auch als Variable namens alpha angegeben. Er ist optional und wird in der Funktionsfarbnotation nach der / angegeben.

rgb(from #00800080 r g b / alpha)             /* alpha=50% */
rgb(from rgba(0,128,0,.5) r g b / alpha)      /* alpha=50% */
rgb(from rgb(0 128 0 / 50%) r g b / alpha)    /* alpha=50% */

calc() oder andere CSS-Funktionen auf den Variablen verwenden

Bisher haben wir die Farbe Grün immer wieder neu erstellt. Syntax lernen und sich mit den Schritten zur Umwandlung und Destrukturierung vertraut machen. Jetzt ist es an der Zeit, die Variablen zu ändern und die Ausgabe so zu ändern, dass sie sich von der Eingabe unterscheidet.

green                              /*  h=120 s=100% l=25%  */
hsl(from green calc(h * 2) s l)    /*  h=240 s=100% l=25%  */

Jetzt ist es dunkelblau. Der Farbton wurde verdoppelt, sodass aus 120 240 wurde, was die Farbe vollständig veränderte. Dadurch wurde der Farbton entlang des Farbkreises gedreht. Ein netter Trick, der mit zylindrischen Farbräumen wie HSL, HWB, LCH und OKLCH sehr einfach ist.

Mit diesem Tool für relative Farbsyntax-Kanalwerte kannst du die Werte der Kanäle visuell sehen, damit du die Berechnungen genau vornehmen kannst, ohne zu raten oder die Spezifikationen auswendig zu lernen. Sie sehen den Wert jedes Kanals basierend auf der von Ihnen angegebenen Syntax. So wissen Sie genau, welche Werte verfügbar sind.

Browserunterstützung prüfen

@supports (color: rgb(from white r g b)) {
  /* safe to use relative color syntax */
}

Anwendungsfälle und Demonstrationen

Für die folgenden Beispiele und Anwendungsfälle gibt es viele alternative Syntaxen, mit denen ähnliche oder dieselben Ergebnisse erzielt werden können. Die Unterschiede ergeben sich aus den Farbräumen und den Kanälen, die sie anbieten.

Außerdem werden in vielen Beispielen Farbanpassungen mit den Begriffen by und to gezeigt. Eine Farbänderung by ist eine relative Farbänderung. Dabei wird der Wert der Variablen verwendet und eine Anpassung anhand des aktuellen Werts vorgenommen. Eine Farbänderung to ist eine absolute Farbänderung. Dabei wird nicht der Wert der Variablen verwendet, sondern ein völlig neuer Wert angegeben.

Alle Demos finden Sie in dieser Codepen-Sammlung.

Farbe aufhellen

Die Farbräume OKLCH, OKLAB, XYZ oder sRGB liefern die vorhersehbarsten Ergebnisse beim Aufhellen von Farben.

Um einen bestimmten Wert aufhellen

Im folgenden Beispiel .lighten-by-25 wird die Farbe blue in OKLCH konvertiert und dann wird das Blau aufgehellt, indem der Kanal l (Helligkeit) durch Multiplizieren des aktuellen Werts mit 1.25 erhöht wird. Dadurch wird die Blautönung um 25 % heller.

.lighten-by-25 {
  background: oklch(from blue calc(l * 1.25) c h);
}

Auf einen bestimmten Wert aufhellen

Im folgenden Beispiel .lighten-to-75 wird der Kanal l nicht verwendet, um blue aufzuhellen. Stattdessen wird der Wert vollständig durch 75% ersetzt.

.lighten-to-75 {
  background: oklch(from blue 75% c h);
}

Farbe verdunkeln

Dieselben Farbräume, die eine Farbe effektiv aufhellen, eignen sich auch hervorragend zum Abdunkeln.

Um einen bestimmten Wert verdunkeln

Im folgenden Beispiel .darken-by-25 wird die Farbe Blau in OKLCH konvertiert und dann abgedunkelt, indem der Kanal l (Helligkeit) um 25% verringert wird, indem der Wert mit .75 multipliziert wird. Dadurch wird die blaue Farbe um 25 % in Richtung Schwarz verschoben.

.darken-by-25 {
  background: oklch(from blue calc(l * .75) c h);
}

Zu einem bestimmten Wert verdunkeln

Im folgenden Beispiel wird der l-Kanal nicht verwendet, um blue abzudunkeln. Stattdessen wird der Wert durch 25% ersetzt..darken-to-25

.darken-to-25 {
  background: oklch(from blue 25% c h);
}

Farbe sättigen

Sättigung um einen Betrag

Im folgenden Beispiel .saturate-by-50 wird der s aus hsl() verwendet, um die Leuchtkraft von orchid um einen relativen 50% zu erhöhen.

.saturate-by-50 {
  background: hsl(from orchid h calc(s * 1.5) l);
}

Bis zu einem bestimmten Wert sättigen

Im folgenden Beispiel .saturate-to-100 wird der s-Kanal aus hsl() nicht verwendet. Stattdessen wird ein gewünschter Sättigungswert angegeben. In diesem Beispiel wird die Sättigung auf 100% erhöht.

.saturate-to-100 {
  background: hsl(from orchid h 100% l);
}

Farbe entsättigen

Um einen bestimmten Wert entsättigen

Im folgenden Beispiel .desaturate-by-half wird der s aus hsl() verwendet, um die Sättigung von indigo um die Hälfte zu verringern.

.desaturate-by-half {
  background: hsl(from indigo h calc(s / 2) l);
}

Entsättigung auf einen bestimmten Wert

Anstatt die Farbsättigung um einen bestimmten Wert zu verringern, können Sie sie auf einen bestimmten gewünschten Wert senken. Im folgenden Beispiel .desaturate-to-25 wird eine neue Farbe auf der Grundlage von indigo erstellt, die Sättigung wird jedoch auf 25 % festgelegt.

.desaturate-to-25 {
  background: hsl(from indigo h 25% l);
}

Farbe mit Chroma verstärken

Dieser Effekt ähnelt dem Saturieren einer Farbe, unterscheidet sich aber in einigen Punkten. Erstens ist es eine chroma-Änderung und keine saturation-Änderung. Das liegt daran, dass die Farbräume, die in einen hohen Dynamikbereich erweitert werden können, keine Sättigung verwenden. Die Farbräume mit chroma unterstützen den High Dynamic Range, sodass Creator die Farbbrillanz noch stärker steigern können als mit der Sättigung.

.increase-chroma {
  background: oklch(from orange l calc(c + .1) h);
}

Deckkraft einer Farbe anpassen

Eine halbtransparente Variante einer Farbe zu erstellen, ist eine der häufigsten Farbanpassungen in Designsystemen. Sehen Sie sich das Beispiel in der Einführung dieses Artikels an, falls Sie es verpasst haben. Dort wird der Problemraum sehr gut dargestellt.

Deckkraft um einen bestimmten Wert anpassen

.decrease-opacity-by-25 {
  background: rgb(from lime r g b / calc(alpha / 2));
}

Deckkraft auf einen bestimmten Wert anpassen

.decrease-opacity-to-25 {
  background: rgb(from lime r g b / 25%);
}

Farbe umkehren

Die Farbumkehr ist eine gängige Funktion zur Farbanpassung in Farbbibliotheken. Eine Möglichkeit besteht darin, eine Farbe in RGB umzuwandeln und dann den Wert jedes Kanals von 1 abzuziehen.

.invert-each-rgb-channel {
  background: rgb(from yellow calc(255 - r) calc(255 - g) calc(255 - b));
}

Komplementärfarbe

Wenn Sie eine Farbe nicht invertieren, sondern ergänzen möchten, ist die Farbtonrotation wahrscheinlich die richtige Wahl. Wählen Sie einen Farbraum aus, in dem der Farbton als Winkel angegeben ist, und drehen Sie den Farbton dann mit calc() um den gewünschten Betrag. Das Komplement einer Farbe wird durch eine halbe Drehung ermittelt. In diesem Fall können Sie dem h-Kanal 180 hinzufügen oder von ihm abziehen, um das Ergebnis zu erhalten.

.complementary-color {
  background: hsl(from blue calc(h + 180) s l);
}

Farbe kontrastieren

L* (Lstar) ist eine Methode, um barrierefreie Farbkontrastverhältnisse zu erreichen. Dabei wird der (ungefähr) wahrnehmungseinheitliche Helligkeitskanal (L) aus LCH und OKLCH in einem calc() verwendet. Je nachdem, ob Sie einen niedrigen, mittleren oder hohen Kontrast anstreben, beträgt das L&M-Delta etwa 40, 50 oder 60.

Diese Methode funktioniert gut für jeden Farbton in LCH oder OKLCH.

Kontrast mit einer dunkleren Farbe

Die Klasse .well-contrasting-darker-color zeigt L* mit einem Delta von 60. Da die ursprüngliche Farbe dunkel ist (niedriger Helligkeitswert), werden dem Helligkeitskanal 60% (0,6) hinzugefügt. Mit dieser Methode wird eine gut kontrastierende, dunkle Textfarbe mit demselben Farbton auf einem hellen Hintergrund gefunden.

.well-contrasting-darker-color {
  background: darkred;
  color: oklch(from darkred calc(l + .60) c h);
}

Kontrast mit einer helleren Farbe

Die Klasse .well-contrasting-lighter-color zeigt auch L* mit einem Delta von 60 %. Da die ursprüngliche Farbe eine helle Farbe ist (hoher Helligkeitswert), wird 0,60 vom Helligkeitskanal abgezogen.

.well-contrasting-lighter-color {
  background: lightpink;
  color: oklch(from lightpink calc(l - .60) c h);
}

Farbpaletten

Die relative Farbsyntax eignet sich sehr gut zum Erstellen von Farbpaletten. Aufgrund der Anzahl der verfügbaren Farbräume ist es besonders nützlich und leistungsstark. In den folgenden Beispielen wird immer OKLCH verwendet, da der Helligkeitskanal zuverlässig ist und der Farbtonkanal ohne Nebenwirkungen gedreht werden kann. Das letzte Beispiel zeigt eine Kombination aus Helligkeits- und Farbtoneinstellungen für ein interessanteres Ergebnis.

Öffnen Sie den Beispiel-Quellcode und ändern Sie die --base-color, um zu sehen, wie dynamisch diese Paletten sind. Das macht Spaß!

Wenn Sie Videos mögen, finden Sie auf YouTube detaillierte Informationen zum Erstellen von Farbpaletten in CSS mit OKLCH.

Monochrome Paletten

Eine einfarbige Palette besteht aus nur einer Farbe, aber mit unterschiedlichen Helligkeits- und Dunkelheitsgraden. Die mittlere Farbe ist die Ausgangsfarbe für die Palette, wobei auf beiden Seiten zwei hellere und zwei dunklere Varianten platziert werden.

:root {
  --base-color: deeppink;

  --color-0: oklch(from var(--base-color) calc(l + .20) c h); /* lightest */
  --color-1: oklch(from var(--base-color) calc(l + .10) c h);
  --color-2: var(--base-color);
  --color-3: oklch(from var(--base-color) calc(l - .10) c h);
  --color-4: oklch(from var(--base-color) calc(l - .20) c h); /* darkest */
}
Paletten mit relativer Farbsyntax und OKLCH ausprobieren

Open Props ist eine Bibliothek mit kostenlosen CSS-Variablen, die Farbpaletten mit dieser Strategie bietet und sie durch Importieren einfach nutzbar macht. Außerdem basieren sie alle auf einer Farbe, die Sie anpassen können. Sie geben einfach eine Farbe an und es wird eine Palette generiert.

Analoge Paletten

Da die Farbtonrotation mit OKLCH und HSL so einfach ist, ist es ein Kinderspiel, eine analoge Farbpalette zu erstellen. Drehen Sie den Farbton so, dass Sie mit dem Ergebnis zufrieden sind, und ändern Sie die Grundfarbe. Der Browser erstellt dann neue Paletten.

:root {
  --base-color: blue;

  --primary:   var(--base-color);
  --secondary: oklch(from var(--base-color) l c calc(h - 45));
  --tertiary:  oklch(from var(--base-color) l c calc(h + 45));
}

Triadische Paletten

Ähnlich wie Komplementärfarben sind Triade-Farbpaletten gegensätzliche, aber harmonische Farbtonrotationen, die auf einer Grundfarbe basieren. Während eine Komplementärfarbe sich auf der gegenüberliegenden Seite einer Farbe befindet, wie eine gerade Linie, die durch die Mitte des Farbkreises gezogen wird, sind triadische Paletten wie ein Dreieck aus Linien, bei denen zwei Farben gleichmäßig um eine Grundfarbe gedreht werden. Drehen Sie dazu den Farbton 120deg.

Das ist eine leichte Vereinfachung der Farbtheorie, aber es reicht aus, um einen Einstieg in die komplexeren triadischen Paletten zu finden, wenn Sie daran interessiert sind.

:root {
  --base-color: yellow;
  --triad-1: oklch(from var(--base-color) l c calc(h - 120));
  --triad-2: oklch(from var(--base-color) l c calc(h + 120));
}

Tetradische Paletten

Tetradische Paletten bestehen aus vier Farben, die gleichmäßig um das Farbrad verteilt sind. Das ergibt eine Palette ohne klaren dominanten Wert. Sie können sich das auch als zwei Paare komplementärer Farben vorstellen. Bei richtiger Anwendung kann sie sehr aussagekräftig sein.

Das ist eine leichte Vereinfachung der Farbtheorie, aber es reicht aus, um einen Einstieg in die komplexeren tetradischen Paletten zu finden, wenn Sie daran interessiert sind.

:root {
  --base-color: lime;

  --color-1: var(--base-color);
  --color-2: oklch(from var(--base-color) l c calc(h + 90));
  --color-3: oklch(from var(--base-color) l c calc(h + 180));
  --color-4: oklch(from var(--base-color) l c calc(h + 270));
}

Einfarbig mit einer leichten Farbtonrotation

Viele Farbexperten haben diesen Trick auf Lager. Das Problem ist, dass eine einfarbige Farbskala ziemlich langweilig sein kann. Die Lösung besteht darin, jeder neuen Farbe bei der Änderung der Helligkeit entweder eine kleine oder eine große Farbtonänderung hinzuzufügen.

Im folgenden Beispiel wird die Helligkeit bei jedem Farbfeld um 10% verringert und der Farbton um 10 Grad gedreht. Das Ergebnis ist eine Palette von Hotpink bis Indigo, die sich nahtlos wie ein Farbverlauf vermischt.

:root {
  --base-color: deeppink;

  --color-1: var(--base-color);
  --color-2: oklch(from var(--base-color) calc(l - .10) c calc(h - 10));
  --color-3: oklch(from var(--base-color) calc(l - .20) c calc(h - 20));
  --color-4: oklch(from var(--base-color) calc(l - .30) c calc(h - 30));
  --color-5: oklch(from var(--base-color) calc(l - .40) c calc(h - 40));
}
Diese Bestenliste mit OKLCH und Farbtonrotation ausprobieren

Die folgende Bestenliste verwendet diese Strategie. Für jedes Listenelement wird sein Index im Dokument als Variable namens --i erfasst. Anhand dieses Index werden dann Farbsättigung, Helligkeit und Farbton angepasst. Die Anpassung beträgt nur 5% oder 5 Grad, also viel subtiler als im obigen Beispiel mit „deeppink“. Es erfordert also ein scharfes Auge, um den Grund dafür zu erkennen, dass diese Bestenliste mit so viel Eleganz in jeder Farbe dargestellt werden kann.

Ändern Sie den Farbton im Schieberegler unter der Bestenliste und sehen Sie, wie mit der relativen Farbsyntax wunderschöne Farbmomente entstehen.

li {
  --_bg: oklch(
    /* decrease lightness as list grows */
    calc(75% - (var(--i) * 5%))

    /* decrease chroma as list grows */
    calc(.2 - (var(--i) * .01))

    /* lightly rotate the hue as the list grows */
    calc(var(--hue) - (var(--i) + 5))
  );
}