Verwendung relativer Farben

Das CSS-Farbmodul definiert die relativen Farbsyntax, die es ermöglicht, einen CSS-<color>-Wert relativ zu einer anderen Farbe zu definieren. Dies ist ein leistungsstarkes Feature, das die einfache Erstellung von Ergänzungen zu bestehenden Farben ermöglicht — wie hellere, dunklere, gesättigte, halbdurchsichtige oder invertierte Varianten — und so eine effektivere Erstellung von Farbpaletten ermöglicht.

Dieser Artikel erklärt die relative Farbsyntax, zeigt die verschiedenen Optionen auf und beleuchtet einige anschauliche Beispiele.

Allgemeine Syntax

Ein relativer CSS-Farbwert hat die folgende allgemeine Syntaxstruktur:

css
color-function(from origin-color channel1 channel2 channel3)
color-function(from origin-color channel1 channel2 channel3 / alpha)

/* color space included in the case of color() functions */
color(from origin-color colorspace channel1 channel2 channel3)
color(from origin-color colorspace channel1 channel2 channel3 / alpha)

Relative Farben werden mit denselben Farb-Funktionen wie absolute Farben erstellt, jedoch mit unterschiedlichen Parametern:

  1. Schließen Sie eine grundlegende Farbfunktion (dargestellt durch color-function() oben) wie rgb(), hsl() usw. ein. Welche Sie wählen, hängt von dem Farbmodell ab, das Sie für die relative Farbe verwenden möchten (die Ausgabefarbe).
  2. Geben Sie die Ursprungsfarbe (oben dargestellt durch origin-color) an, auf der Ihre relative Farbe basieren soll, zuvor durch das Schlüsselwort from. Dies kann jeder gültige <color>-Wert sein, der ein beliebiges verfügbares Farbmodell verwendet, einschließlich eines Farbwerts in einer CSS-Benutzerdefinierten Eigenschaft, Systemfarben, currentColor oder sogar eine andere relative Farbe.
  3. Im Fall der color()-Funktion, schließen Sie den colorspace der Ausgabefarbe ein.
  4. Geben Sie einen Ausgabe-Wert für jeden individuellen Kanal an. Die Ausgabefarbe wird nach der Ursprungsfarbe definiert — oben dargestellt durch die Platzhalter channel1, channel2 und channel3. Die hier definierten Kanäle hängen von der Farb-Funktion ab, die Sie für Ihre relative Farbe verwenden. Wenn Sie beispielsweise hsl() verwenden, müssten Sie die Werte für Farbton, Sättigung und Helligkeit definieren. Jeder Kanalwert kann ein neuer Wert sein, derselbe wie der ursprüngliche Wert oder ein Wert, der relativ zum Kanalwert der Ursprungsfarbe ist.
  5. Optional kann ein alpha-Kanalwert vom Typ <alpha-value> für die Ausgabefarbe definiert werden, dem ein Schrägstrich (/) vorangestellt ist. Wenn der alpha-Kanalwert nicht explizit angegeben ist, wird er standardmäßig auf den alpha-Kanalwert der origin-color gesetzt (nicht 100 %, wie es bei absoluten Farbwerten der Fall ist).

Der Browser konvertiert die Ursprungsfarbe in eine mit der Farbfunktion kompatible Syntax und zerlegt sie dann in die Komponentenfarbkanäle (plus den alpha-Kanal, wenn die Ursprungsfarbe einen hat). Diese stehen als geeignete Namen in der Farbfunktion zur Verfügung — r, g, b und alpha im Fall der rgb()-Funktion, l, a, b und alpha im Fall der lab()-Funktion, h, w, b und alpha im Fall von hwb() usw. — die verwendet werden können, um neue Ausgabekanalwerte zu berechnen.

Sehen wir uns die relative Farbsyntax in Aktion an. Das untenstehende CSS wird verwendet, um zwei <div>-Elemente zu stylen, eines mit einer absoluten Hintergrundfarbe — red — und eines mit einer relativen Hintergrundfarbe, die mit der rgb()-Funktion erstellt wurde, basierend auf demselben red-Farbwert:

css
#one {
  background-color: red;
}

#two {
  background-color: rgb(from red 150 g b / alpha);
}

Das Ergebnis ist wie folgt:

Die relative Farbe verwendet die rgb()-Funktion, die red als Ursprungsfarbe nimmt, sie in eine äquivalente rgb()-Farbe (rgb(255 0 0)) konvertiert und dann die neue Farbe mit einem Rotkanal von Wert 200 und grünen, blauen und Alpha-Kanälen definiert, die denselben Wert wie die Ursprungsfarbe haben (sie verwendet die vom Browser bereitgestellten g- und b-Werte innerhalb der Funktion, die beide gleich 0 sind, und das alpha ist 100%).

Dies führt zu einem Ergebnis von rgb(200 0 0) — ein etwas dunkleres Rot. Hätten wir einen Rotkanalwert von 255 (oder einfach den r-Wert) angegeben, wäre die resultierende Ausgabefarbe genau gleich dem Eingabewert. Die endgültige Ausgabefarbe des Browsers (der berechnete Wert) ist ein sRGB-color()-Wert, der rgb(200 0 0) äquivalent ist — color(srgb 0.784314 0 0).

Hinweis: Wie bereits erwähnt, konvertiert der Browser beim Berechnen einer relativen Farbe zunächst die angegebene Ursprungsfarbe (red im obigen Beispiel) in einen Wert, der mit der verwendeten Farbfunktion kompatibel ist (in diesem Fall rgb()). Dies geschieht so, dass der Browser die Ausgabefarbe aus der Ursprungsfarbe berechnen kann. Während die Berechnungen relativ zur verwendeten Farbfunktion durchgeführt werden, hängt der tatsächliche Ausgabefarbwert vom Farbraum der Farbe ab:

  • Ältere sRGB-Farb-Funktionen können das gesamte Spektrum sichtbarer Farben nicht ausdrücken. Die Ausgabefarben von (hsl(), hwb() und rgb()) werden als color(srgb) serialisiert, um diese Einschränkungen zu umgehen. Das bedeutet, dass das Abfragen des Ausgabefarbwerts über die HTMLElement.style-Eigenschaft oder die CSSStyleDeclaration.getPropertyValue()-Methode den Ausgabefarbwert als color(srgb ...)-Wert zurückgibt.
  • Bei neueren Farbfunktionen (lab(), oklab(), lch(), und oklch()) werden relative Farb-Ausgabewerte im selben Syntax geschrieben wie die verwendete Farbfunktion. Beispiel: Wenn eine lab()-Farb-Funktion verwendet wird, ist die Ausgabefarbe ein lab()-Wert.

Alle folgenden Zeilen ergeben eine äquivalente Ausgabefarbe:

css
red
rgb(255 0 0)
rgb(from red 255 0 0)
rgb(from red 255 0 0 / 1)
rgb(from red 255 0 0 / 100%)

rgb(from red 255 g b)
rgb(from red r 0 0)
rgb(from red r g b / 1)
rgb(from red r g b / 100%)

rgb(from red r g b)
rgb(from red r g b / alpha)

/* With `red`, the g and b are the same, making them interchangeable */
rgb(from red r g g)
rgb(from red r b b)
rgb(from red 255 g g)
rgb(from red 255 b b)

Syntax-Flexibilität

Es gibt einen wichtigen Unterschied zwischen den im Funktionsblock bereitgestellten aufgeschlüsselten Ursprungsfarbe-Kanalwerten und den Kanalwerten, die vom Entwickler für die Ausgabefarbe festgelegt werden.

Um es noch einmal zu betonen: Wenn eine relative Farbe definiert ist, stehen die Kanalwerte der Ursprungsfarbe im Funktionsblock zur Verfügung, um die Ausgabefarbe-Kanalwerte zu definieren. Das folgende Beispiel definiert eine relative Farbe mit einer rgb()-Funktion und verwendet die Ursprungsfarbe-Kanalwerte (bereitgestellt als r, g und b) für die Ausgabekanalwerte, was bedeutet, dass die Ausgabefarbe dieselbe ist wie die Ursprungsfarbe:

css
rgb(from red r g b)

Wenn Sie jedoch die Ausgabewerte angeben, müssen Sie die Ursprungsfarbe-Kanalwerte gar nicht verwenden. Sie müssen lediglich sicherstellen, dass die Ausgabekanalwerte in der richtigen Reihenfolge angegeben werden (z. B. Rot, dann Grün, dann Blau im Fall von rgb()), aber sie können beliebige gültige Werte für diese Kanäle sein. Dies gibt relativen CSS-Farben einen hohen Grad an Flexibilität.

Wenn Sie beispielsweise möchten, können Sie absolute Werte wie gezeigt verwenden, um red in blue zu verwandeln:

css
rgb(from red 0 0 255)
/* output color is equivalent to rgb(0 0 255), full blue */

Hinweis: Wenn Sie die relative Farbsyntax verwenden, um dieselbe Farbe wie die Ursprungsfarbe oder eine Farbe zu erzeugen, die überhaupt nicht auf der Ursprungsfarbe basiert, erzeugen Sie keine wirkliche relative Farbe. Dies würden Sie wahrscheinlich niemals in einer echten Codebasis tun und stattdessen einfach einen absoluten Farbwert verwenden. Aber wir hielten es für nützlich, zu erklären, dass Sie dies mit der relativen Farbsyntax tun können, als Ausgangspunkt zum Lernen darüber.

Sie können sogar die bereitgestellten Werte mischen oder wiederholen. Das folgende Beispiel nimmt ein etwas dunkleres Rot als Eingabe und gibt eine hellgraue Farbe aus — die r, g und b-Kanäle der Ausgabefarbe sind alle auf den r-Kanalwert der Ursprungsfarbe gesetzt:

css
rgb(from rgb(200 0 0) r r r)
/* output color is equivalent to rgb(200 200 200), light gray */

Das folgende Beispiel verwendet die Ursprungsfarbe-Kanalwerte für die r, g und b-Kanalwerte der Ausgabefarbe, jedoch in umgekehrter Reihenfolge:

css
rgb(from rgb(200 170 0) b g r)
/* output color is equivalent to rgb(0 170 200) */

Farb-Funktionen, die relative Farben unterstützen

Im obigen Abschnitt haben wir nur relative Farben gesehen, die über die rgb()-Funktion definiert wurden. Allerdings können relative Farben mit jeder modernen CSS-Farb-Funktion definiert werden — color(), hsl(), hwb(), lab(), lch(), oklab(), oklch(), oder rgb(). Die allgemeine Syntaxstruktur ist in jedem Fall dieselbe, auch wenn die Ursprungsfarbwerte unterschiedliche Namen haben, die der verwendeten Funktion entsprechen.

Unten finden Sie Beispiele für relative Farbsyntax für jede Farbfunktion. Jeder Fall ist der einfachste mögliche, wobei die Ausgabefarbe-Kanalwerte genau mit den Ursprungsfarbe-Kanalwerten übereinstimmen:

css
/* color() with and without alpha channel */
color(from red a98-rgb r g b)
color(from red a98-rgb r g b / alpha)

color(from red xyz-d50 x y z)
color(from red xyz-d50 x y z / alpha)

/* hsl() with and without alpha channel */
hsl(from red h s l)
hsl(from red h s l / alpha)

/* hwb() with and without alpha channel */
hwb(from red h w b)
hwb(from red h w b / alpha)

/* lab() with and without alpha channel */
lab(from red l a b)
lab(from red l a b / alpha)

/* lch() with and without alpha channel */
lch(from red l c h)
lch(from red l c h / alpha)

/* oklab() with and without alpha channel */
oklab(from red l a b)
oklab(from red l a b / alpha)

/* oklch() with and without alpha channel */
oklch(from red l c h)
oklch(from red l c h / alpha)

/* rgb() with and without alpha channel */
rgb(from red r g b)
rgb(from red r g b / alpha)

Es sei nochmals erwähnt, dass das Farbsystem der Ursprungsfarbe nicht mit dem Farbsystem übereinstimmen muss, das zur Erstellung der Ausgabefarbe verwendet wird. Auch dies bietet viel Flexibilität. Im Allgemeinen werden Sie nicht daran interessiert sein, und vielleicht wissen Sie nicht einmal, in welchem System die Ursprungsfarbe definiert ist (Sie könnten einfach einen Manipulationswert einer benutzerdefinierten Eigenschaft haben). Sie möchten einfach eine Farbe eingeben und zum Beispiel eine hellere Variante davon erstellen, indem Sie sie in eine hsl()-Funktion stecken und den Helligkeitswert variieren.

Verwendung benutzerdefinierter Eigenschaften

Bei der Erstellung einer relativen Farbe können Sie Werte verwenden, die in CSS-Benutzerdefinierten Eigenschaften sowohl für die Ursprungsfarbe als auch innerhalb der Definitionen der Ausgabefarbe-Kanalwerte definiert sind. Sehen wir uns ein Beispiel an.

Im untenstehenden CSS definieren wir zwei benutzerdefinierte Eigenschaften:

  • --base-color enthält unsere Basis-Markenfarbe — purple. Hier verwenden wir eine benannte Farbbezeichnung, aber relative Farben können jede Farbsyntax für die Ursprungsfarbe akzeptieren.
  • --standard-opacity enthält den Standard-Marken-Opazitätswert, den wir auf halbdurchsichtige Boxen anwenden möchten — 0.75.

Wir geben dann zwei <div>-Elementen eine Hintergrundfarbe. Eines erhält eine absolute Farbe — unser --base-color Markenlila. Das andere erhält eine relative Farbe, die unserem Markenlila entspricht, transformiert, um einen Alphakanal hinzuzufügen, der unserem Standard-Opazitätswert entspricht.

css
:root {
  --base-color: purple;
  --standard-opacity: 0.75;
}

#one {
  background-color: var(--base-color);
}

#two {
  background-color: hwb(from var(--base-color) h w b / var(--standard-opacity));
}

Das Ergebnis ist wie folgt:

Verwendung mathematischer Funktionen

Sie können CSS-Mathefunktionen wie calc() verwenden, um Werte für die Ausgabefarbkanäle zu berechnen. Sehen wir uns ein Beispiel an.

Das untenstehende CSS wird verwendet, um drei <div>-Elemente mit unterschiedlichen Hintergrundfarben zu stylen. Das mittlere erhält eine unveränderte --base-color, während das linke und das rechte mit aufgehellten und abgedunkelten Varianten dieser --base-color versehen werden. Diese Varianten werden mithilfe relativer Farben definiert — die --base-color wird in eine lch()-Funktion übertragen, und die Ausgabefarbe hat ihren Helligkeitskanal modifiziert, um den gewünschten Effekt zu erzielen, über eine calc()-Funktion. Die aufgehellte Farbe hat 20 % zum Helligkeitskanal addiert, und die abgedunkelte Farbe hat 20 % davon subtrahiert.

css
:root {
  --base-color: orange;
}

#one {
  background-color: lch(from var(--base-color) calc(l + 20) c h);
}

#two {
  background-color: var(--base-color);
}

#three {
  background-color: lch(from var(--base-color) calc(l - 20) c h);
}

Das Ergebnis ist wie folgt:

Manipulation des Alphakanals

Dieses Beispiel zeigt die Änderung des Alphakanals einer benannten Farbe. Hier haben wir ein Element, das in einen Container eingebettet ist, und beide haben einen teal Hintergrund. Um zwischen den Hintergründen zu unterscheiden, variieren wir den Wert des Alphakanals unter Verwendung der relativen Farb-Funktion, der calc()-Funktion und einer benutzerdefinierten Eigenschaft.

html
<div class="container">
  <div class="item"></div>
</div>
css
div {
  background-color: rgb(
    from teal r g b / calc(alpha * var(--alpha-multiplier))
  );
}

.container {
  --alpha-multiplier: 0.3;
}

.item {
  --alpha-multiplier: 1;
}

Der Alphakanal wird mit dem Schlüsselwort alpha referenziert. In diesem Fall modifiziert der Ausdruck calc(alpha * var(--alpha-multiplier)) den Wert des Alphakanals, indem alpha mit dem --alpha-multiplier einer benutzerdefinierten Eigenschaft multipliziert wird. Der Container erhält einen halbdurchsichtigen Hintergrund, da der Multiplikator von 0.3 kleiner als 1.0 ist.

Das Ergebnis ist wie folgt:

Kanalwerte werden auf <number>-Werte aufgelöst

Um Rechnungen mit Kanalwerten in relativen Farben zu ermöglichen, werden alle Ursprungsfarbkanalwerte in entsprechende <number>-Werte aufgelöst. Zum Beispiel berechnen wir in den lch()-Beispielen oben neue Helligkeitswerte, indem wir Zahlen zum l-Kanalwert der Ursprungsfarbe addieren oder davon abziehen. Wenn wir calc(l + 20%) versuchen würden, würde das zu einer ungültigen Farbe führen — l ist ein <number> und kann nicht um ein <percentage> ergänzt werden.

  • Kanalwerte, die ursprünglich als <percentage> spezifiziert wurden, werden auf einen <number>-Wert aufgelöst, der für die Ausgabefarb-Funktion geeignet ist.
  • Kanalwerte, die ursprünglich als <hue> Winkel spezifiziert wurden, werden auf eine Anzahl von Grad in einem Bereich von 0 bis 360 aufgelöst, einschließlich.

Überprüfen Sie die verschiedenen Seiten zu Farbfunktionen für die spezifischen Details, in was ihre Ursprungsfarbenskalen aufgelöst werden.

Überprüfen der Browser-Unterstützung

Sie können überprüfen, ob ein Browser die relative Farbsyntax unterstützt, indem Sie sie durch ein @supports at-rule laufen lassen.

Beispiel:

css
@supports (color: hsl(from white h s l)) {
  /* safe to use hsl() relative color syntax */
}

Beispiele

Hinweis: Weitere Beispiele zur Demonstration der Verwendung der relativen Farbsyntax in den verschiedenen funktionalen Notationstypen finden Sie auf ihren dedizierten Seiten: color(), hsl(), hwb(), lab(), lch(), oklab(), oklch(), rgb().

Farbpalettengenerator

Dieses Beispiel ermöglicht Ihnen die Auswahl einer Grundfarbe und eines Farbpalette-Typs. Der Browser zeigt dann eine entsprechende Palette von Farben basierend auf der gewählten Grundfarbe an. Die Farbpalettenoptionen sind wie folgt:

  • Komplementär: Beinhaltet zwei Farben, die sich auf gegenüberliegenden Seiten eines Farbkreises befinden, oder mit anderen Worten, gegenteilige Farbtöne (siehe den <hue> Datentyp für weitere Informationen zu Farbtönen und Farbkreisen). Die beiden Farben werden als Grundfarbe und die Grundfarbe mit Farbtonkanal +180 Grad definiert.
  • Triadisch: Beinhaltet drei Farben, die gleich weit um den Farbkreis herum liegen. Die drei Farben werden als Grundfarbe, Grundfarbe mit Farbtonkanal -120 Grad und Grundfarbe mit Farbtonkanal +120 Grad definiert.
  • Tetradisch: Beinhaltet vier Farben, die gleich weit um den Farbkreis herum liegen. Die vier Farben werden als Grundfarbe und Grundfarbe mit Farbtonkanal +90, +180 und +270 Grad definiert.
  • Monochrom: Beinhaltet mehrere Farben mit gleichem Farbton, aber verschiedenen Helligkeitswerten. In unserem Beispiel haben wir fünf Farben in einer monochromen Palette definiert — Grundfarbe und Grundfarbe mit Helligkeitskanal -20, -10, +10 und +20.

HTML

Das vollständige HTML ist unten zur Referenz enthalten. Die interessantesten Teile sind wie folgt:

  • Die benutzerdefinierte --base-color-Eigenschaft wird als Inline-style auf dem <div>-Element mit der ID container gespeichert. Wir haben es dort platziert, damit es einfach mit JavaScript aktualisiert werden kann. Wir haben einen Initialwert von #ff0000 (red) angegeben, um eine Farbpalette basierend auf diesem Wert anzuzeigen, wenn das Beispiel geladen wird. Beachten Sie, dass wir dies normalerweise wahrscheinlich auf dem <html>-Element setzen würden, aber das MDN-Live-Beispiel hat dies beim Rendern entfernt.
  • Der Farbwertwähler wird mit einem <input type="color">-Steuerelement erstellt. Wenn ein neuer Wert in diesem Steuerelement festgelegt wird, wird die --base-color-benutzerdefinierte Eigenschaft mit diesem Wert über JavaScript festgelegt, was wiederum eine neue Farbpalette erzeugt. Alle angezeigten Farben sind relative Farben basierend auf --base-color.
  • Der Satz von <input type="radio">-Steuerelementen ermöglicht die Auswahl eines zu generierenden Farbpaletten-Typs. Wenn hier ein neuer Wert ausgewählt wird, wird mit JavaScript eine neue Klasse auf dem container-<div> festgelegt, um den gewählten Palette-Typ darzustellen. In CSS werden Nachkom-Selektoren verwendet, um die Kind-<div>s anzusteuern (z. B. .comp :nth-child(1)), so dass sie die richtigen Farben erhalten und die ungenutzten <div>-Knoten versteckt werden.
  • Das container-<div>, das die Kind-<div>s enthält, die die Farben der generierten Palette anzeigen. Beachten Sie, dass zunächst eine Klasse comp darauf festgelegt ist, so dass die Seite ein komplementäres Farbschema anzeigt, wenn sie erstmalig geladen wird.
html
<div>
  <h1>Color palette generator</h1>
  <form>
    <div id="color-picker">
      <label for="color">Select a base color:</label>
      <input type="color" id="color" name="color" value="#ff0000" />
    </div>
    <div>
      <fieldset>
        <legend>Select a color palette type:</legend>

        <div>
          <input
            type="radio"
            id="comp"
            name="palette-type"
            value="comp"
            checked />
          <label for="comp">Complementary</label>
        </div>

        <div>
          <input
            type="radio"
            id="triadic"
            name="palette-type"
            value="triadic" />
          <label for="triadic">Triadic</label>
        </div>

        <div>
          <input
            type="radio"
            id="tetradic"
            name="palette-type"
            value="tetradic" />
          <label for="tetradic">Tetradic</label>
        </div>

        <div>
          <input
            type="radio"
            id="monochrome"
            name="palette-type"
            value="monochrome" />
          <label for="monochrome">Monochrome</label>
        </div>
      </fieldset>
    </div>
  </form>
  <div id="container" class="comp">
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
  </div>
</div>

CSS

Unten zeigen wir nur das CSS, das die Palettenfarben festlegt. Beachten Sie, wie in jedem Fall Nachkom-Selektoren verwendet werden, um die richtige background-color auf jedes Kind-<div>-Element für die gewählte Palette anzuwenden. Wir kümmern uns mehr um die Position der <div>s in der Quellreihenfolge als um den Elementtyp, so dass wir :nth-child verwenden, um sie anzusprechen.

Im letzten Regelblock haben wir den allgemeinen Geschwister-Selektor (~) verwendet, um die ungenutzten <div>-Elemente in jedem Paletten-Typ anzusprechen, und display: none gesetzt, um deren Darstellung zu verhindern.

Die Farben selbst beinhalten die --base-color plus relative Farben, die von dieser --base-color abgeleitet sind. Die relativen Farben verwenden die lch()-Funktion — sie geben die Ursprungs---base-color weiter und definieren eine Ausgabefarbe mit angepassten Helligkeits- oder Farbtonkanal je nach Bedarf.

css
/* Complementary colors */
/* Base color, and base color with hue channel +180 degrees */

.comp :nth-child(1) {
  background-color: var(--base-color);
}

.comp :nth-child(2) {
  background-color: lch(from var(--base-color) l c calc(h + 180));
}

/* Use @supports to add in support old syntax that requires deg units
   to be specified in hue calculations. This is required for Safari 16.4+. */
@supports (color: lch(from red l c calc(h + 180deg))) {
  .comp :nth-child(2) {
    background-color: lch(from var(--base-color) l c calc(h + 180deg));
  }
}

/* Triadic colors */
/* Base color, base color with hue channel -120 degrees, and base color */
/* with hue channel +120 degrees */

.triadic :nth-child(1) {
  background-color: var(--base-color);
}

.triadic :nth-child(2) {
  background-color: lch(from var(--base-color) l c calc(h - 120));
}

.triadic :nth-child(3) {
  background-color: lch(from var(--base-color) l c calc(h + 120));
}

/* Use @supports to add in support old syntax that requires deg units
   to be specified in hue calculations. This is required for Safari 16.4+. */
@supports (color: lch(from red l c calc(h + 120deg))) {
  .triadic :nth-child(2) {
    background-color: lch(from var(--base-color) l c calc(h - 120deg));
  }

  .triadic :nth-child(3) {
    background-color: lch(from var(--base-color) l c calc(h + 120deg));
  }
}

/* Tetradic colors */
/* Base color, and base color with hue channel +90, +180, and +270 degrees */

.tetradic :nth-child(1) {
  background-color: var(--base-color);
}

.tetradic :nth-child(2) {
  background-color: lch(from var(--base-color) l c calc(h + 90));
}

.tetradic :nth-child(3) {
  background-color: lch(from var(--base-color) l c calc(h + 180));
}

.tetradic :nth-child(4) {
  background-color: lch(from var(--base-color) l c calc(h + 270));
}

/* Use @supports to add in support old syntax that requires deg units
   to be specified in hue calculations. This is required for Safari 16.4+. */
@supports (color: lch(from red l c calc(h + 90deg))) {
  .tetradic :nth-child(2) {
    background-color: lch(from var(--base-color) l c calc(h + 90deg));
  }

  .tetradic :nth-child(3) {
    background-color: lch(from var(--base-color) l c calc(h + 180deg));
  }

  .tetradic :nth-child(4) {
    background-color: lch(from var(--base-color) l c calc(h + 270deg));
  }
}

/* Monochrome colors */
/* Base color, and base color with lightness channel -20, -10, +10, and +20 */

.monochrome :nth-child(1) {
  background-color: lch(from var(--base-color) calc(l - 20) c h);
}

.monochrome :nth-child(2) {
  background-color: lch(from var(--base-color) calc(l - 10) c h);
}

.monochrome :nth-child(3) {
  background-color: var(--base-color);
}

.monochrome :nth-child(4) {
  background-color: lch(from var(--base-color) calc(l + 10) c h);
}

.monochrome :nth-child(5) {
  background-color: lch(from var(--base-color) calc(l + 20) c h);
}

/* Hide unused swatches for each palette type */
.comp :nth-child(2) ~ div,
.triadic :nth-child(3) ~ div,
.tetradic :nth-child(4) ~ div {
  display: none;
}
Ein Exkurs zum @supports-Test

Im Beispiel-CSS werden Ihnen verschiedene @supports-Blöcke auffallen, die verwendet werden, um andere background-color-Werte für Browser bereitzustellen, die eine frühere Entwurfsspezifikation der relativen Farbsyntax unterstützen. Diese sind erforderlich, da die ursprüngliche Implementierung von Safari auf einer älteren Version der Spezifikation basierte, in der Ursprungsfarbe-Kanalwerte je nach Kontext zu <number>en oder anderen Einheitstypen aufgelöst wurden. Dies bedeutete, dass Werte manchmal Einheiten benötigten, wenn Additionen und Subtraktionen durchgeführt wurden, was Verwirrung stiftete. In neueren Implementierungen werden Ursprungsfarbe-Kanalwerte immer auf einen äquivalenten <number>-Wert aufgelöst, was bedeutet, dass Berechnungen immer mit einheitenlosen Werten durchgeführt werden.

Beachten Sie, wie der Unterstützungstest in jedem Fall unter Verwendung einer beliebigen Farberklärung durchgeführt wird — color: lch(from red l c calc(h + 90deg)) zum Beispiel — nicht notwendigerweise den tatsächlichen Wert, den wir für andere Browser variieren müssen. Beim Testen von komplexen Werten wie diesen sollten Sie die einfachste mögliche Deklaration verwenden, die immer noch den syntaktischen Unterschied enthält, den Sie testen möchten.

Das Einschließen einer benutzerdefinierten Eigenschaft im @supports-Test funktioniert nicht — der Test fällt immer positiv aus, unabhängig davon, welcher Wert der benutzerdefinierten Eigenschaft gegeben wird. Dies liegt daran, dass ein benutzerdefinierter Eigenschaftswert nur dann ungültig wird, wenn er einem ungültigen Wert (oder einem Teil eines ungültigen Wertes) einer regulären CSS-Eigenschaft zugewiesen wird. Um dies zu umgehen, haben wir in jedem Test var(--base-color) durch das Schlüsselwort red ersetzt.

JavaScript

Im JavaScript:

  • Fügen wir ein change Ereignis-Listener zu den Radiobuttons hinzu, sodass, wenn einer ausgewählt wird, die setContainer()-Funktion ausgeführt wird. Diese Funktion aktualisiert den class-Wert des <div> mit id="container" mit dem Wert des ausgewählten Radiobuttons, sodass die richtigen Hintergrundfarben auf die Kind-<div>s für den gewählten Paletten-Typ angewendet werden.
  • Fügen wir ein input Ereignis-Listener zu dem Farbwertwähler-Steuerelement hinzu, sodass, wenn eine neue Farbe ausgewählt wird, die setBaseColor()-Funktion ausgeführt wird. Diese Funktion setzt den Wert der benutzerdefinierten --base-color-Eigenschaft auf die neue Farbe.
js
const form = document.forms[0];
const radios = form.elements["palette-type"];
const colorPicker = form.elements["color"];
const containerElem = document.getElementById("container");

for (const radio of radios) {
  radio.addEventListener("change", setContainer);
}

colorPicker.addEventListener("input", setBaseColor);

function setContainer(e) {
  const palType = e.target.value;
  console.log("radio changed");
  containerElem.setAttribute("class", palType);
}

function setBaseColor(e) {
  console.log("color changed");
  containerElem.style.setProperty("--base-color", e.target.value);
}

Ergebnisse

Das Ergebnis ist wie folgt. Dies beginnt, die Leistungsfähigkeit relativer CSS-Farben zu zeigen — wir definieren mehrere Farben und generieren Paletten, die live aktualisiert werden, indem ein einziger benutzerdefinierter Eigenschaftswert eingestellt wird.

Live-UI-Farbschema-Aktualisierer

Dieses Beispiel zeigt eine Karte mit einer Überschrift und einem Text, jedoch mit einem Twist — unterhalb der Karte befindet sich ein Schieberegler-(<input type="range">)-Steuerelement. Wenn sein Wert geändert wird, wird JavaScript verwendet, um einen --hue-Wert für benutzerdefinierte Eigenschaften auf diesen neuen Schiebereglerwert einzustellen.

Dies wiederum passt das Farbschema für die gesamte UI an:

  • Der --base-color-Wert ist eine relative Farbe mit ihrem Farbtonkanal auf den --hue-Wert eingestellt.
  • Die anderen in der Gestaltung verwendeten Farben sind relative Farben basierend auf --base-color. Infolgedessen ändern sie sich, wenn die --base-color geändert wird.

HTML

Das HTML für das Beispiel wird unten angezeigt.

  • Das <main>-Element fungiert als äußerer Wrapper, der den Rest des Inhalts enthält und es ermöglicht, dass die Karte und das Formular vertikal und horizontal innerhalb der <main>-Elemente als eine Einheit zentriert werden.
  • Das <section>-Element enthält die <h1>- und <p>-Elemente, die den Inhalt der Karte definieren.
  • Das <form>-Element enthält das (<input type="range">)-Steuerelement und seine <label>.
html
<main>
  <section>
    <h1>A love of colors</h1>
    <p>
      Colors, the vibrant essence of our surroundings, are truly awe-inspiring.
      From the fiery warmth of reds to the calming coolness of blues, they bring
      unparalleled richness to our world. Colors stir emotions, ignite
      creativity, and shape perceptions, acting as a universal language of
      expression. In their brilliance, colors create a visually enchanting
      tapestry that invites admiration and sparks joy.
    </p>
  </section>
  <form>
    <label for="hue-adjust">Adjust the hue:</label>
    <input
      type="range"
      name="hue-adjust"
      id="hue-adjust"
      value="240"
      min="0"
      max="360" />
  </form>
</main>

CSS

Im CSS ist im :root ein Standard---hue-Wert festgelegt, relative lch()-Farben, um das Farbschema zu definieren, sowie ein radialer Verlauf, der den gesamten Körper ausfüllt.

Die relative Farben sind wie folgt:

  • --base-color: Die Basisfarbe nimmt eine Ursprungsfarbe von red (obwohl jede volle Farbe geeignet wäre) und passt ihren Farbtonwert an den in der --hue-Eigenschaft gesetzten Wert an.
  • --bg-color: Eine viel hellere Variante von --base-color, gedacht als Hintergrund. Diese wird erstellt, indem eine Ursprungsfarbe von --base-color genommen und 40 zu ihrem Helligkeitswert hinzugefügt wird.
  • --complementary-color: Eine Komplementärfarbe, die 180 Grad um den Farbkreis von --base-color liegt. Diese wird erstellt, indem eine Ursprungsfarbe von --base-color genommen und 180 zu ihrem Farbtonwert hinzugefügt wird.

Schauen Sie sich nun den Rest des CSS an und beachten Sie alle Stellen, an denen diese Farben verwendet werden. Dies umfasst Hintergründe, Ränder, text-shadow und sogar die accent-color des Schiebereglers.

Hinweis: Zur Veranschaulichung werden nur die für die Verwendung relativer Farben relevanten Teile des CSS gezeigt.

css
:root {
  /* Default hue value */
  --hue: 240;

  /* Relative color definitions */
  --base-color: lch(from red l c var(--hue));
  --bg-color: lch(from var(--base-color) calc(l + 40) c h);
  --complementary-color: lch(from var(--base-color) l c calc(h + 180));

  background: radial-gradient(ellipse at center, white 20%, var(--base-color));
}

/* Use @supports to add in support for --complementary-color with old
   syntax that requires deg units to be specified in hue calculations.
   This is required for in Safari 16.4+. */
@supports (color: lch(from red l c calc(h + 180deg))) {
  body {
    --complementary-color: lch(from var(--base-color) l c calc(h + 180deg));
  }
}

/* Box styling */

section {
  background-color: var(--bg-color);
  border: 3px solid var(--base-color);
  border-radius: 20px;
  box-shadow: 10px 10px 30px rgb(0 0 0 / 0.5);
}

h1 {
  background-color: var(--base-color);
  text-shadow:
    1px 1px 1px var(--complementary-color),
    -1px -1px 1px var(--complementary-color),
    0 0 3px var(--complementary-color);
}

/* Range slider styling */

form {
  background-color: var(--bg-color);
  border: 3px solid var(--base-color);
}

input {
  accent-color: var(--complementary-color);
}

JavaScript

Das JavaScript fügt dem Schieberegler ein input-Ereignis-Listener hinzu, damit, wenn ein neuer Wert eingestellt wird, die setHue()-Funktion ausgeführt wird. Diese Funktion setzt einen neuen Inline---hue-Wert für benutzerdefinierte Eigenschaften im :root (dem <html>-Element), der den ursprünglich in unserem CSS gesetzten Standardwert überschreibt.

js
const rootElem = document.querySelector(":root");
const slider = document.getElementById("hue-adjust");

slider.addEventListener("input", setHue);

function setHue(e) {
  rootElem.style.setProperty("--hue", e.target.value);
}

Ergebnisse

Das Ergebnis wird unten gezeigt. Relative CSS-Farben werden hier verwendet, um das Farbschema einer gesamten Benutzeroberfläche zu steuern, die live angepasst werden kann, während ein einzelner Wert geändert wird.

Siehe auch