Grundlegende Übersicht über das Einrichten eines dynamischen und konfigurierbaren Farbschemas
In diesem Beitrag möchte ich einige Überlegungen zur Verwaltung mehrerer Farbschemas in CSS vorstellen. Demo ansehen.
Wenn Sie lieber ein Video ansehen möchten, finden Sie hier eine YouTube-Version dieses Beitrags:
Übersicht
Wir erstellen ein barrierefreies Farbsystem mit benutzerdefinierten Eigenschaften und calc(), um eine Webseite zu erstellen, die sich an die Nutzereinstellungen anpasst und gleichzeitig den Aufwand für die Erstellung minimiert. Wir beginnen mit einer primären Markenfarbe und entwickeln daraus ein System von Varianten: zwei Textfarben, vier Oberflächenfarben und ein passender Schatten.
In diesem Leitfaden werden zuerst alle Farben für die einzelnen Farbschemas definiert. Sie werden erst ganz am Ende verwendet, um die Seite zu ändern.
Die Marke
Häufig ist bereits eine Markenfarbe festgelegt, die als Hexadezimalcode oder RGB-Code angegeben wird. Die Grundfarbe der Marke für diese GUI-Challenge ist #0af. Zuerst muss der Hex-Wert für dieses Farbsystem in hsl konvertiert werden.
* {
--brand: #0af;
--brand: hsl(200 100% 50%);
}
Um das Konzept des Abdunkelns oder Aufhellens der Markenfarbe um beispielsweise 20 % zu ermöglichen, müssen die drei Channels des HSL-Farbwerts in eigene benutzerdefinierte Eigenschaften extrahiert werden:
* {
--brand-hue: 200;
--brand-saturation: 100%;
--brand-lightness: 50%;
}
CSS kann Berechnungen für diese Farbeigenschaften durchführen, z. B. calc(var(--brand-lightness) -
20%), um den Helligkeitswert um 20 % zu verringern. Das ist die Grundlage für die Erstellung eines Farbschemas, da mit CSS alle Farben in derselben Farbtonfamilie gehalten werden können, indem die HSL-Sättigungs- und Helligkeitswerte angepasst werden.
Helles Design
Jede Farbvariante wird mit dem entsprechenden Schema gekennzeichnet. In diesem Fall wird jede mit -light ergänzt.

Marke
Ausgehend von der Markenfarbe wird sie neu erstellt, indem die benutzerdefinierten Eigenschaften --brand-hue, --brand-saturation und --brand-lightness in die Klammern der HSL-Funktion () eingeschlossen werden, ohne dass Berechnungen erforderlich sind:
* {
--brand-light: hsl(var(--brand-hue) var(--brand-saturation) var(--brand-lightness));
}
Schriftfarben
Als Nächstes benötigen Sie Textfarben für das Farbschema. In einem hellen Design sollte der Text sehr dunkel sein. Die Helligkeit der folgenden Farben ist gering, deutlich unter 50%.
* {
--text1-light: hsl(var(--brand-hue) var(--brand-saturation) 10%);
--text2-light: hsl(var(--brand-hue) 30% 30%);
}
--text1-light, da es bei 10% Helligkeit sehr dunkel ist, wird die hohe Sättigung von 100 % beibehalten, damit die Markenfarbe auch im dunklen Marineblau noch durchscheinen kann.
--text2-light ist nicht ganz so dunkel wie die erste Farbe, was gut ist, da es sich um eine sekundäre Farbe handelt. Außerdem ist sie viel weniger gesättigt.
Oberflächenfarben
Oberflächenfarben sind die Hintergründe, Rahmen und anderen dekorativen Oberflächen, auf oder in denen sich Text befindet. In einem hellen Design sind das die hellen Farben im Gegensatz zu den dunklen Textfarben. Um helle Farben mit HSL zu erstellen, verwenden wir höhere Prozentwerte für den dritten Helligkeitswert. Außerdem wird die Sättigung verringert, damit die hellen Grautöne nicht zu stark getönt aussehen.
* {
--surface1-light: hsl(var(--brand-hue) 25% 90%);
--surface2-light: hsl(var(--brand-hue) 20% 99%);
--surface3-light: hsl(var(--brand-hue) 20% 92%);
--surface4-light: hsl(var(--brand-hue) 20% 85%);
}
Es wurden vier Oberflächenfarben erstellt, da für dekorative Farben in der Regel mehr Varianten erforderlich sind, z. B. für interaktive Momente wie :focus oder :hover oder um den Eindruck von Papierschichten zu erwecken. In diesen Fällen ist es sinnvoll, beim Hovern von --surface2-light zu --surface3-light zu wechseln, da dies zu einem erhöhten Kontrast führt (99% Helligkeit zu 92% Helligkeit; das Element wird dunkler).
Schatten
Schatten in einem Farbschema sind mehr als nur ein zusätzliches Element. Sie verleihen dem Effekt eine lebensechte Note und heben ihn von unrealistischen schwarzen Schatten ab. Dazu wird für die Farbe des Schattens die benutzerdefinierte Farbton-Property verwendet. Die Farbe ist leicht gesättigt, aber dennoch sehr dunkel. Im Grunde wird ein sehr dunkler, leicht blauer Schatten erzeugt.
* {
--surface-shadow-light: var(--brand-hue) 10% 20%;
--shadow-strength-light: .02;
}
--surface-shadow-light ist nicht in einer HSL-Funktion enthalten. Das liegt daran, dass der Wert --shadow-strength kombiniert wird, um eine gewisse Deckkraft zu erzielen. CSS benötigt die einzelnen Teile, um Berechnungen durchzuführen. Weitere Informationen zum Radschatten
Lichtfarben zusammen
Sie müssen nicht lange suchen, um herauszufinden, wie die einzelnen hellen Farben erstellt werden, da sie alle an einem Ort im CSS zu finden sind.
* {
--brand-light: hsl(var(--brand-hue) var(--brand-saturation) var(--brand-lightness));
--text1-light: hsl(var(--brand-hue) var(--brand-saturation) 10%);
--text2-light: hsl(var(--brand-hue) 30% 30%);
--surface1-light: hsl(var(--brand-hue) 25% 90%);
--surface2-light: hsl(var(--brand-hue) 20% 99%);
--surface3-light: hsl(var(--brand-hue) 20% 92%);
--surface4-light: hsl(var(--brand-hue) 20% 85%);
--surface-shadow-light: var(--brand-hue) 10% calc(var(--brand-lightness) / 5);
--shadow-strength-light: .02;
}
Dunkles Design
Die meisten Marken beginnen nicht mit einem dunklen Design, sondern mit einer Variante ihres primären, in der Regel helleren Designs. Nutzer wählen das dunkle Design hingegen oft für verschiedene Kontexte aus, z. B. nachts. Aus diesen Gründen habe ich bei der Entwicklung von dunklen Designs zwei Dinge berücksichtigt:
- Nutzer verwenden dieses Design in der Regel im Dunkeln. Testen Sie es daher auch im Dunkeln.
- Die Farben sollten entsättigt werden, damit sie nicht zu intensiv sind und auf dem Bildschirm flimmern.

Marke
Im hellen Design wurden die drei HSL-Farbkanalwerte der Marke unverändert verwendet, im dunklen Design nicht. Die Sättigung wird halbiert und die Helligkeit um 50 % reduziert.
* {
--brand-dark: hsl(
var(--brand-hue)
calc(var(--brand-saturation) / 2)
calc(var(--brand-lightness) / 1.5)
);
}
Schriftfarben
In einem dunklen Design sollten die Textfarben hell sein. Die folgenden Farben haben hohe Werte für die Helligkeit, wodurch sie näher an Weiß liegen.
* {
--text1-dark: hsl(var(--brand-hue) 15% 85%);
--text2-dark: hsl(var(--brand-hue) 5% 65%);
}
Oberflächenfarben
In einem dunklen Design sollten die Oberflächenfarben dunkel sein. Die folgenden Farben haben eine geringe Helligkeit und Sättigung. Die erste Oberfläche ist mit 10 % die dunkelste.
* {
--surface1-dark: hsl(var(--brand-hue) 10% 10%);
--surface2-dark: hsl(var(--brand-hue) 10% 15%);
--surface3-dark: hsl(var(--brand-hue) 5% 20%);
--surface4-dark: hsl(var(--brand-hue) 5% 25%);
}
Schatten
In einem dunklen Design sind Schatten möglicherweise nur schwer zu erkennen. Das ist sinnvoll, da es schwierig ist, etwas abzudunkeln, das bereits ziemlich dunkel ist. Hier ist --shadow-strength-dark sehr praktisch, da wir die Schatten durch Ändern einer Variablen verdunkeln können.
* {
--surface-shadow-dark: var(--brand-hue) 50% 3%;
--shadow-strength-dark: .8;
}
Achten Sie auch darauf, wie viel Sättigung im Schatten vorhanden ist. Sehen Sie die Farbe, wenn Sie sich die Benutzeroberfläche ansehen? Entferne die Sättigung aus den Entwicklertools. Welche Version gefällt dir besser?
Dunkle Farben insgesamt
* {
--brand-dark: hsl(var(--brand-hue) calc(var(--brand-saturation) / 2) calc(var(--brand-lightness) / 1.5));
--text1-dark: hsl(var(--brand-hue) 15% 85%);
--text2-dark: hsl(var(--brand-hue) 5% 65%);
--surface1-dark: hsl(var(--brand-hue) 10% 10%);
--surface2-dark: hsl(var(--brand-hue) 10% 15%);
--surface3-dark: hsl(var(--brand-hue) 5% 20%);
--surface4-dark: hsl(var(--brand-hue) 5% 25%);
--surface-shadow-dark: var(--brand-hue) 50% 3%;
--shadow-strength-dark: .8;
}
Gedämpftes Design
Bei diesem Farbschema geht es darum, Helligkeit und Sättigung aufeinander abzustimmen. Die Sättigung sollte hoch genug sein, damit noch ein Farbton sichtbar ist, aber auch nur knapp die Kontrastwerte erreichen, da sie ohnehin schwach und kontrastarm sein soll.

Marke
* {
--brand-dim: hsl(
var(--brand-hue)
calc(var(--brand-saturation) / 1.25)
calc(var(--brand-lightness) / 1.25)
);
}
Schriftfarben
* {
--text1-dim: hsl(var(--brand-hue) 15% 75%);
--text2-dim: hsl(var(--brand-hue) 10% 61%);
}
Oberflächenfarben
* {
--surface1-dim: hsl(var(--brand-hue) 10% 20%);
--surface2-dim: hsl(var(--brand-hue) 10% 25%);
--surface3-dim: hsl(var(--brand-hue) 5% 30%);
--surface4-dim: hsl(var(--brand-hue) 5% 35%);
}
Schatten
* {
--surface-shadow-dim: var(--brand-hue) 30% 13%;
--shadow-strength-dim: .2;
}
Farben insgesamt dimmen
* {
--brand-dim: hsl(var(--brand-hue) calc(var(--brand-saturation) / 1.25) calc(var(--brand-lightness) / 1.25));
--text1-dim: hsl(var(--brand-hue) 15% 75%);
--text2-dim: hsl(var(--brand-hue) 10% 61%);
--surface1-dim: hsl(var(--brand-hue) 10% 20%);
--surface2-dim: hsl(var(--brand-hue) 10% 25%);
--surface3-dim: hsl(var(--brand-hue) 5% 30%);
--surface4-dim: hsl(var(--brand-hue) 5% 35%);
--surface-shadow-dim: var(--brand-hue) 30% 13%;
--shadow-strength-dim: .2;
}
Barrierefreie Farben
Die niedrigste Helligkeit im dunklen Textfarbsatz beträgt 65% und die höchste Helligkeit bei dunklen Oberflächen 25%. Das entspricht einem Helligkeitsunterschied von 40 %. Im hellen Design gibt es 55% mehr Platz. Wenn Sie die Helligkeitsunterschiede zwischen Text- und Oberflächenfarben bei etwa 40–50% halten, können Sie für ein hohes Farbkontrastverhältnis sorgen. Außerdem ist dies eine gute Möglichkeit, um die Werte anzupassen, falls sie schlecht sind.
Ich nenne es „bump bump til ya pass“, was bedeutet, dass ich den Helligkeitswert so lange erhöhe, bis ein Tool anzeigt, dass ich die Anforderungen erfülle.
Alle in dieser Challenge erstellten Designs haben die Kontrastanforderungen erfüllt. Das dunkle Farbschema hat den niedrigsten Kontrast, erfüllt aber dennoch die Mindestanforderungen. Damit andere im Team kontrastreiche Farben verwenden können, ist es sinnvoll, einen Klassennamen zu erstellen, der eine Oberflächenfarbe mit einer zugänglichen Textfarbe kombiniert.
.surface1 {
background-color: var(--surface1);
color: var(--text2);
}
.surface2 {
background-color: var(--surface2);
color: var(--text2);
}
.surface3 {
background-color: var(--surface3);
color: var(--text1);
}
.surface4 {
background-color: var(--surface4);
color: var(--text1);
}
Rad Shadow
Die Themes verwenden eine Utility-Klasse namens .rad-shadow. Dieser Schatten wurde mit dem Tool für weiche Schatten generiert, was ich sehr schätze. Ich habe den generierten Snippet übernommen und mit meinen eigenen Farben und Berechnungen für die Deckkraft angepasst. Der Grund dafür war, einen Schatten zu erstellen, den ich in jedem Farbschema anpassen konnte.

Dazu habe ich für jedes Farbschema zwei Variablen erstellt: eine Schattenfarbe und eine Schattenstärke. Die Farbe dient zur Anpassung von Sättigung und Dunkelheit, während die Stärke eine einfache Möglichkeit bietet, die Schattenintensität bei einem dunklen Farbschema zu erhöhen. Das Endergebnis sah in etwa so aus.
:root {
--surface-shadow-light: var(--brand-hue) 10% 20%;
--shadow-strength-light: .02;
}
.rad-shadow {
box-shadow:
0 2.8px 2.2px hsl(var(--surface-shadow) / calc(var(--shadow-strength) + .03)),
0 6.7px 5.3px hsl(var(--surface-shadow) / calc(var(--shadow-strength) + .01)),
0 12.5px 10px hsl(var(--surface-shadow) / calc(var(--shadow-strength) + .02)),
0 22.3px 17.9px hsl(var(--surface-shadow) / calc(var(--shadow-strength) + .02)),
0 41.8px 33.4px hsl(var(--surface-shadow) / calc(var(--shadow-strength) + .03)),
0 100px 80px hsl(var(--surface-shadow) / var(--shadow-strength))
;
}
Wenn ich Schatten in meinem Farbschema verwenden würde, würde ich die Schattenwinkel auch als Design-Token-Konstante festlegen, da die Lichtrichtung für alle Schatten des Designs gleich sein sollte.
Verwendung der Farbschemata
Nachdem die Farben vordefiniert wurden, müssen sie in schemabezogene Eigenschaften umgewandelt werden. Als CSS-Autor in diesem Farbschema-Projekt sollte man nur selten auf den Wert eines bestimmten Farbschemas zugreifen müssen. Ich möchte es euch leicht machen, das Thema einzuhalten.
Dazu muss die Verwendung des Farbschemas ausschließlich über die generischen benutzerdefinierten Eigenschaften erfolgen, die wir gleich definieren werden. So müssen sich Nutzer der Designvariablen nie Gedanken darüber machen, welches Farbschema gerade festgelegt ist. Sie müssen nur die Oberflächen- und Textfarben verwenden. Verwenden Sie color: var(--text1) statt color: var(--text1-light). Alle Anpassungen und Änderungen von Farben erfolgen auf einer viel höheren Ebene im CSS.
Die verbindenden Stile des hellen Designs im folgenden Codeblock verknüpfen eine generische benutzerdefinierte Eigenschaft mit der farbspezifischen Farbe des hellen Designs. Ab sofort wird für alle Verwendungen von var(--brand) die helle Markenfarbe verwendet.
Helles Design (automatisch)
:root {
color-scheme: light;
--brand: var(--brand-light);
--text1: var(--text1-light);
--text2: var(--text2-light);
--surface1: var(--surface1-light);
--surface2: var(--surface2-light);
--surface3: var(--surface3-light);
--surface4: var(--surface4-light);
--surface-shadow: var(--surface-shadow-light);
--shadow-strength: var(--shadow-strength-light);
}
Für die Website wird jetzt das helle Design verwendet. Das ist ein sehr schöner Moment! Sehen wir uns noch ein paar Beispiele an, in denen wir unsere vordefinierten Farben in anderen Farbschemakontexten verwenden.
Dunkles Design (automatisch)
@media (prefers-color-scheme: dark) {
:root {
color-scheme: dark;
--brand: var(--brand-dark);
--text1: var(--text1-dark);
--text2: var(--text2-dark);
--surface1: var(--surface1-dark);
--surface2: var(--surface2-dark);
--surface3: var(--surface3-dark);
--surface4: var(--surface4-dark);
--surface-shadow: var(--surface-shadow-dark);
--shadow-strength: var(--shadow-strength-dark);
}
}
Helles Design
[color-scheme="light"] {
color-scheme: light;
--brand: var(--brand-light);
--text1: var(--text1-light);
--text2: var(--text2-light);
--surface1: var(--surface1-light);
--surface2: var(--surface2-light);
--surface3: var(--surface3-light);
--surface4: var(--surface4-light);
--surface-shadow: var(--surface-shadow-light);
--shadow-strength: var(--shadow-strength-light);
}
Dunkles Design
[color-scheme="dark"] {
color-scheme: dark;
--brand: var(--brand-dark);
--text1: var(--text1-dark);
--text2: var(--text2-dark);
--surface1: var(--surface1-dark);
--surface2: var(--surface2-dark);
--surface3: var(--surface3-dark);
--surface4: var(--surface4-dark);
--surface-shadow: var(--surface-shadow-dark);
--shadow-strength: var(--shadow-strength-dark);
}
Gedämpftes Design
[color-scheme="dim"] {
color-scheme: dark;
--brand: var(--brand-dim);
--text1: var(--text1-dim);
--text2: var(--text2-dim);
--surface1: var(--surface1-dim);
--surface2: var(--surface2-dim);
--surface3: var(--surface3-dim);
--surface4: var(--surface4-dim);
--surface-shadow: var(--surface-shadow-dim);
--shadow-strength: var(--shadow-strength-dim);
}
An diesem Punkt können Autoren die bereitgestellten generischen Farbschemas nach Bedarf verwenden und müssen sich nie wieder Gedanken über Designs machen.
Fazit
Jetzt wissen Sie, wie ich es gemacht habe. Wie würden Sie es machen? 🙂
Wir möchten unsere Ansätze diversifizieren und alle Möglichkeiten kennenlernen, die das Web bietet. Erstelle einen Codepen oder hoste deine eigene Demo, sende mir einen Tweet mit dem Link und ich füge sie unten im Abschnitt „Community-Remixe“ hinzu.
Quelle
Community-Remixe
- @chris-kruining hat einen Farbton-Schieberegler, Statusfarben und Kontrastmodi für no-preference, more und less hinzugefügt: Demo.