Eine grundlegende Übersicht zum Erstellen eines dynamischen und konfigurierbaren Farbschemas
In diesem Beitrag möchte ich meine Gedanken zu Möglichkeiten zur Verwaltung mehrerer Farbschemata in CSS teilen. Demo ansehen.
Wenn du lieber ein Video ansiehst, findest du 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 die Erstellung vereinfacht. Wir beginnen mit einer Basisfarbe der Marke und erstellen daraus ein System von Varianten: zwei Textfarben, vier Oberflächenfarben und einen passenden Schatten.
In diesem Leitfaden werden zuerst alle Farben für jedes Farbschema definiert. Erst ganz am Ende werden sie verwendet, um die Seite zu wechseln.
Die Marke
Oft ist bereits eine Markenfarbe festgelegt, die als Hex-Farbe oder RGB-Farbe übermittelt wird. Die Basismarke dieser GUI-Herausforderung hat die Farbe #0af
. Zuerst muss der Hexadezimalwert für dieses Farbsystem in hsl konvertiert werden.
* {
--brand: #0af;
--brand: hsl(200 100% 50%);
}
Damit die Markenfarbe um beispielsweise 20 % abgedunkelt oder aufgehellt werden kann, müssen die drei Kanäle des HSL-Farbwerts in eigene benutzerdefinierte Eigenschaften extrahiert werden. So gehts:
* {
--brand-hue: 200;
--brand-saturation: 100%;
--brand-lightness: 50%;
}
In CSS können diese Farbeigenschaften mathematisch verarbeitet werden, z. B. calc(var(--brand-lightness) -
20%)
, um den Helligkeitswert um 20 % zu verringern. Dies ist die Grundlage für die Erstellung eines Farbschemas, da CSS alle Farben in derselben Farbfamilie beibehalten kann, indem die Sättigung und Helligkeit in hsl angepasst wird.
Helles Design
Jede Farbvariante wird mit dem entsprechenden Farbschema gekennzeichnet. In diesem Fall wird jeder Variante -light
angehängt.
Marke
Beginnend mit 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 Berechnungen:
* {
--brand-light: hsl(var(--brand-hue) var(--brand-saturation) var(--brand-lightness));
}
Schriftfarben
Als Nächstes benötigen Sie Textfarben. Bei einem hellen Design sollte der Text sehr dunkel sein. Beachten Sie, dass die Helligkeit der folgenden Farben niedrig ist, 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, behält es die hohe Sättigung von 100 % bei, damit die Markenfarbe immer noch durch das dunkle Marineblau hindurchscheint.
--text2-light
, sie ist nicht ganz so dunkel wie die erste Farbe, was gut ist, da es sich um eine Sekundärfarbe handelt. Außerdem ist sie viel weniger gesättigt.
Oberflächenfarben
Oberflächenfarben sind die Hintergründe, Rahmen und anderen dekorativen Oberflächen, auf denen oder in denen Text angezeigt wird. Bei einem hellen Design sind dies die hellen Farben, im Gegensatz zu den dunklen Textfarben. Um mit hsl helle Farben zu erstellen, verwenden wir im dritten Helligkeitswert höhere Prozentwerte. Außerdem senken wir die Sättigung, damit die hellgrauen Farben nicht zu getönt wirken.
* {
--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 Elemente wie :focus
oder :hover
oder um das Aussehen von Papierschichten zu erzeugen. In diesen Fällen ist es sinnvoll, beim Hovering von --surface2-light
zu --surface3-light
zu wechseln, damit ein Hovering zu einem höheren Kontrast führt (von 99% Helligkeit auf 92% Helligkeit, also dunkler).
Schatten
Schatten in einem Farbschema sind zwar nicht unbedingt erforderlich, verleihen dem Effekt aber eine naturgetreue Wirkung und helfen ihm, sich von unrealistischen schwarzbasierten Schatten abzuheben. Dazu wird für die Farbe des Schattens die benutzerdefinierte Property „Farbton“ verwendet. Der Farbton 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 eine HSL-Funktion eingeschlossen. Das liegt daran, dass der Wert --shadow-strength
kombiniert wird, um eine gewisse Deckkraft zu erzielen, und CSS die einzelnen Teile benötigt, um Berechnungen durchzuführen. Weitere Informationen finden Sie im Abschnitt Schatten des Rades.
Helle Farben zusammen
Sie müssen nicht lange suchen, um herauszufinden, wie die Lichtfarben erstellt werden. Sie finden sie alle an einem Ort im CSS.
* {
--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 dagegen häufig ein dunkles Design für unterschiedliche Kontexte, z. B. für die Nacht. Aufgrund dieser Faktoren habe ich bei dunklen Designs zwei Dinge im Hinterkopf:
- Nutzer werden dieses Design in der Regel bei Dunkelheit verwenden. Testen Sie es also bei Dunkelheit.
- Die Farben sollten möglichst gedeckt sein, damit sie auf dem Bildschirm nicht zu grell wirken.
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 relativ um 50 % reduziert.
* {
--brand-dark: hsl(
var(--brand-hue)
calc(var(--brand-saturation) / 2)
calc(var(--brand-lightness) / 1.5)
);
}
Schriftfarben
Bei einem dunklen Design sollten die Textfarben hell sein. Die folgenden Farben haben hohe Helligkeitswerte und sind daher heller als Weiß.
* {
--text1-dark: hsl(var(--brand-hue) 15% 85%);
--text2-dark: hsl(var(--brand-hue) 5% 65%);
}
Oberflächenfarben
Bei 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 % am dunkelsten.
* {
--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
Im dunklen Design sind Schatten oft kaum zu erkennen. Das macht Sinn, da es schwierig ist, etwas abzudunkeln, das bereits ziemlich dunkel ist. Hier kommt --shadow-strength-dark
ins Spiel, da wir damit 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 stark dieser Schatten gesättigt ist. Können Sie die Farbe sehen, wenn Sie sich die Benutzeroberfläche ansehen? Versuchen Sie, die Sättigung in den DevTools zu entfernen. Was gefällt Ihnen besser?
Dunkle Farben zusammen
* {
--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;
}
Dunkles Design
Bei diesem Farbschema geht es darum, Helligkeit und Sättigung zu kombinieren. Die Sättigung sollte ausreichen, damit der Farbton noch sichtbar ist, aber auch nur knapp die Kontrastwerte erreichen, da sie ohnehin dunkel 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;
}
Alle Farben gleichzeitig 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 Satz der dunklen Textfarben beträgt 65% und die höchste Helligkeit in den dunklen Oberflächen 25%. Das entspricht 40% der Helligkeit und einem gewissen Spielraum zwischen ihnen. Im hellen Design ist ein Weißraum von 55% vorhanden. Wenn Sie die Helligkeitsunterschiede zwischen Text- und Oberflächenfarben bei etwa 40–50% halten, können Sie die Farbkontrastverhältnisse hoch halten. Außerdem haben Sie so einen subtilen Hebel, um Anpassungen vorzunehmen, falls die Bewertungen 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 den Pass erreiche.
Alle in dieser Herausforderung erstellten Themen erreichen gute Kontrastwerte. Das gedimmte Farbschema hat den niedrigsten Kontrast, erfüllt aber dennoch die Mindestanforderungen. Damit andere Teammitglieder gut kontrastierende Farben verwenden können, ist es eine gute Idee, eine Klassenbezeichnung zu erstellen, die eine Oberflächenfarbe mit einer barrierefreien 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);
}
Radschatten
Die Themen verwenden eine Dienstprogrammklasse namens .rad-shadow
. Dieser Schatten wurde mit dem Tool Smooth Shadow generiert, das ich sehr schätze. Ich habe das generierte Snippet mit meinen eigenen Farben und Opacity-Berechnungen angepasst. Der Grund dafür war, einen Schatten zu erstellen, den ich innerhalb jedes Farbschemas anpassen konnte.
Dazu habe ich für jedes Farbschema zwei Variablen erstellt, die angepasst werden können: eine Schattenfarbe und eine Schattenstärke. Mit der Farbe können Sie die Sättigung und Dunkelheit anpassen. Mit der Stärke lässt sich die Schattenintensität bei einem dunklen Farbschema ganz einfach 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 mit Schatten in meinem Farbschema noch weiter gehen würde, würde ich auch die Schattenwinkel zu einem Design-Token machen, da die Lichtrichtung zwischen allen Schatten des Designs gleich sein sollte.
Verwendung der Farbschemata
Nachdem die Farben vordefiniert wurden, ist es an der Zeit, sie in schemaunabhängige Eigenschaften umzuwandeln. Als CSS-Entwickler in diesem Farbschema-Projekt sollten Sie nur selten auf den Wert eines bestimmten Farbschemas zugreifen müssen. Ich möchte es Ihnen so einfach wie möglich machen, sich an das Thema zu halten.
Dazu sollte das Farbschema ausschließlich über die generischen benutzerdefinierten Properties verwendet werden, die wir gleich definieren. So müssen sich die Nutzer der Designvariablen keine Gedanken mehr darüber machen, welches Farbschema derzeit festgelegt ist. Sie müssen nur die Oberflächen- und Textfarben verwenden. Verwenden Sie anstelle von color: var(--text1-light)
color: var(--text1)
. Die Anpassung und Neuausrichtung von Farben erfolgt auf einer viel höheren Ebene im CSS.
Im folgenden Codeblock werden die Verbindungsstile des hellen Designs veranschaulicht. Dabei wird eine generische benutzerdefinierte Eigenschaft mit der für das helle Design spezifischen Farbe verknüpft. Jetzt 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);
}
Die Website verwendet jetzt das helle Design. Das ist ein sehr schöner Moment. Sehen wir uns noch ein paar weitere Beispiele an, in denen wir unsere vordefinierten Farben in anderen Farbschema-Kontexten 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);
}
Dunkles 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);
}
Autoren können die bereitgestellten generischen Farbschemata nach Bedarf verwenden und müssen sich nie wieder Gedanken über Themen machen.
Fazit
Jetzt, da Sie wissen, wie ich das gemacht habe, wie würden Sie es machen? 🙂
Lassen Sie uns unsere Ansätze diversifizieren und alle Möglichkeiten kennenlernen, wie Sie im Web entwickeln können. Erstelle einen Codepen oder hoste deine eigene Demo, tweete mir einen Link dazu und ich füge sie unten in den Abschnitt „Community-Remixe“ ein.
Quelle
Community-Remixe: @chris-kruining hat einen Farbtonregler, Statusfarben und Kontrastmodi für no-preference
, more
und less
hinzugefügt: Demo.