Una panoramica di base su come stabilire una combinazione di colori dinamica e configurabile
In questo post voglio condividere alcune idee su come gestire più combinazioni di colori in CSS. Prova la demo.
Se preferisci i video, ecco una versione di questo post su YouTube:
Panoramica
Creeremo un sistema di colori accessibile con proprietà personalizzate e calc(), per
creare una pagina web adattabile alle preferenze dell'utente, mantenendo al contempo l'esperienza
di creazione al minimo. Partiamo da un colore di base del brand e creiamo un sistema di
varianti: 2 colori del testo, 4 colori della superficie e un'ombra corrispondente.
Questa guida inizia con la definizione di tutti i colori per ogni combinazione di colori. Vengono utilizzati per modificare la pagina solo alla fine.
Il brand
Spesso, il colore del brand è già stato stabilito e viene fornito come
esadecimale o
RGB. Questa sfida GUI
ha un colore di base del brand #0af. Innanzitutto, per questo sistema di colori, il valore esadecimale
deve essere convertito in
hsl.
* {
--brand: #0af;
--brand: hsl(200 100% 50%);
}
Per attivare un concetto di scurimento o schiarimento del colore del brand, ad esempio del 20%, i tre canali del valore del colore HSL devono essere estratti nelle proprie proprietà personalizzate, in questo modo:
* {
--brand-hue: 200;
--brand-saturation: 100%;
--brand-lightness: 50%;
}
CSS può eseguire calcoli su queste proprietà di colore, ad esempio calc(var(--brand-lightness) -
20%) per diminuire il valore di luminosità del 20%. Questo è fondamentale per creare
una combinazione di colori, in quanto CSS può mantenere tutti i colori nella stessa famiglia di tonalità regolando i
valori di saturazione e luminosità HSL.
Tema chiaro
Ogni variante di colore verrà contrassegnata con la combinazione corrispondente, in questo caso
a ciascuna viene aggiunto -light.

Brand
A partire dal colore del brand, viene ricostruito inserendo le proprietà personalizzate --brand-hue, --brand-saturation
e --brand-lightness all'interno delle parentesi della funzione hsl (),
senza alcun calcolo:
* {
--brand-light: hsl(var(--brand-hue) var(--brand-saturation) var(--brand-lightness));
}
Colori testo
Successivamente, gli elementi essenziali di una combinazione di colori richiedono i colori del testo. In un tema chiaro, il testo deve essere molto scuro. Nota come la luminosità dei seguenti colori sia bassa, ben al di sotto del 50%.
* {
--text1-light: hsl(var(--brand-hue) var(--brand-saturation) 10%);
--text2-light: hsl(var(--brand-hue) 30% 30%);
}
--text1-light, poiché è molto scuro al 10% di luminosità, mantiene la saturazione al 100% in modo che il colore del brand possa ancora intravedersi nel blu scuro.
--text2-light, non è scuro come il primo colore, il che è positivo perché è
un colore secondario ed è anche molto meno saturo.
Colori della superficie
I colori della superficie sono gli sfondi, i bordi e altre superfici decorative su cui si trova il testo o all'interno delle quali è contenuto. In un tema chiaro, questi sono i colori chiari, al contrario dei colori del testo che erano scuri. Per creare colori chiari con HSL, utilizzeremo valori percentuali più elevati nel terzo valore di luminosità. Inoltre, diminuiremo la saturazione, in modo che i grigi chiari non appaiano troppo colorati.
* {
--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%);
}
Sono stati creati quattro colori di superficie, poiché i colori decorativi tendono a richiedere più
varianti, per momenti interattivi come :focus o :hover o per creare l'aspetto
di strati di carta. In questi scenari, è preferibile la transizione
--surface2-light al passaggio del mouse a --surface3-light, in modo che il passaggio del mouse aumenti
il contrasto (dal 99% di luminosità al 92% di luminosità, rendendolo più scuro).
Ombre
Le ombre all'interno di una combinazione di colori sono un valore aggiunto, ma conferiscono un aspetto realistico all'effetto e lo aiutano a distinguersi dalle ombre nere non realistiche. Per farlo, il colore dell'ombra utilizzerà la proprietà personalizzata della tonalità, sarà leggermente saturato con la tonalità, ma comunque molto scuro. Fondamentalmente, crea un'ombra molto scura e leggermente blu.
* {
--surface-shadow-light: var(--brand-hue) 10% 20%;
--shadow-strength-light: .02;
}
--surface-shadow-light non è racchiuso in una funzione HSL. Questo perché il
valore --shadow-strength verrà combinato per creare un po' di opacità e il CSS ha bisogno
dei pezzi per eseguire i calcoli. Vai alla sezione
rad shadow per saperne di più.
Colori chiari tutti insieme
Non è necessario cercare come vengono creati i colori della luce, sono tutti in un unico posto nel 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;
}
Tema scuro
La maggior parte dei brand non inizia con un tema scuro, ma con una variante del tema principale, di solito più chiaro. Gli utenti, invece, spesso scelgono un tema scuro per contesti diversi, ad esempio di notte. Questi fattori mi hanno portato a tenere a mente due cose con i temi scuri:
- Gli utenti in genere non vedranno nulla quando utilizzano questo tema, quindi esegui i test al buio.
- I colori devono essere desaturati per non vibrare sullo schermo a causa di un'intensità eccessiva.

Brand
Il tema chiaro utilizzava i valori dei tre canali di colore HSL del brand senza alterazioni, il tema scuro no. La saturazione è dimezzata e la luminosità ridotta di un valore relativo del 50%.
* {
--brand-dark: hsl(
var(--brand-hue)
calc(var(--brand-saturation) / 2)
calc(var(--brand-lightness) / 1.5)
);
}
Colori testo
In un tema scuro, i colori del testo devono essere chiari. I seguenti colori hanno valori elevati per la luminosità, il che li rende più vicini al bianco.
* {
--text1-dark: hsl(var(--brand-hue) 15% 85%);
--text2-dark: hsl(var(--brand-hue) 5% 65%);
}
Colori della superficie
In un tema scuro, i colori della superficie devono essere scuri. I seguenti colori hanno luminosità e saturazione basse, con la prima superficie che è la più scura al 10%.
* {
--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%);
}
Ombre
In un tema scuro, le ombre possono essere molto difficili da vedere. Ha senso, dato che è difficile
oscurare qualcosa che è già abbastanza scuro. È qui che
--shadow-strength-dark diventa molto utile, in quanto ci consente di scurire le
ombre modificando una variabile.
* {
--surface-shadow-dark: var(--brand-hue) 50% 3%;
--shadow-strength-dark: .8;
}
Inoltre, osserva la saturazione dell'ombra. Riesci a notare il colore quando guardi l'interfaccia? Prova a rimuovere la saturazione dagli strumenti di sviluppo. Quale preferisci?
Colori scuri tutti insieme
* {
--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;
}
Tema scuro
Questa combinazione di colori si basa sull'orchestrazione di luminosità e saturazione. La saturazione deve essere sufficiente per rendere visibile una tonalità, ma deve anche superare a malapena i punteggi di contrasto, in quanto è comunque pensata per essere scura e a basso contrasto.

Brand
* {
--brand-dim: hsl(
var(--brand-hue)
calc(var(--brand-saturation) / 1.25)
calc(var(--brand-lightness) / 1.25)
);
}
Colori testo
* {
--text1-dim: hsl(var(--brand-hue) 15% 75%);
--text2-dim: hsl(var(--brand-hue) 10% 61%);
}
Colori della superficie
* {
--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%);
}
Ombre
* {
--surface-shadow-dim: var(--brand-hue) 30% 13%;
--shadow-strength-dim: .2;
}
Diminuire l'intensità di tutti i colori
* {
--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;
}
Colori accessibili
Nota come la luminosità più bassa nel set di colori del testo scuro sia del 65% e la luminosità più alta nelle superfici scure sia del 25%. ovvero il 40% di spazio tra l'uno e l'altro. Nel tema chiaro, c'è il 55% di spazio libero. Mantenere le differenze di luminosità tra il testo e i colori della superficie intorno al 40-50% può contribuire a mantenere elevati i rapporti di contrasto del colore, oltre a essere un leva sottile da regolare nel caso in cui i punteggi siano scarsi.
Lo chiamo "bump bump til ya pass", che è l'interazione di aumentare il valore di luminosità finché uno strumento non mi mostra che ho superato il test.
Tutti i temi creati in questa sfida superano i punteggi di contrasto. Lo schema di colori scuro ha il contrasto più basso, ma soddisfa comunque i requisiti minimi. Per aiutare gli altri membri del team a utilizzare colori con un buon contrasto, è consigliabile creare un nome di classe che accoppi un colore di superficie a un colore del testo accessibile.
.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
I temi utilizzano una classe di utilità chiamata .rad-shadow. Questa ombra è stata generata
con questo strumento Ombra morbida, che apprezzo molto. Ho preso lo snippet generato e l'ho personalizzato con i miei colori e
calcoli di opacità. Il motivo era creare un'ombra che potessi regolare
all'interno di ogni combinazione di colori.

Per farlo, ho creato due variabili per ogni combinazione di colori da regolare: un colore dell'ombra e un'intensità dell'ombra. Il colore serve per regolare la saturazione e l'oscurità, mentre l'intensità è un modo semplice per aumentare l'intensità dell'ombra quando si tratta di una combinazione di colori scuri. Il risultato finale è stato simile a questo.
: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))
;
}
Se dovessi approfondire l'utilizzo delle ombre nella mia combinazione di colori, renderei anche gli angoli delle ombre una costante del token di progettazione, poiché la direzione della luce dovrebbe essere la stessa tra tutte le ombre del progetto.
Utilizzo delle combinazioni di colori
Una volta completata la predefinizione dei colori, è il momento di trasformarli in proprietà indipendenti dallo schema. Ciò che intendo è che, in qualità di autore CSS all'interno di questo progetto di combinazione di colori, raramente è necessario accedere al valore di una combinazione di colori specifica. Voglio fare in modo che sia facile rimanere in tema.
A questo scopo, l'utilizzo della combinazione di colori deve essere eseguito esclusivamente tramite
le proprietà personalizzate generiche, che definiremo tra poco. In questo modo, le persone che utilizzano le variabili di progettazione non devono mai preoccuparsi di quale combinazione di colori è attualmente impostata, ma devono solo utilizzare i colori della superficie e del testo. Invece di
color: var(--text1-light) utilizza color: var(--text1). Tutti gli adattamenti e i cambiamenti
dei colori vengono eseguiti a un livello molto più alto in CSS.
Approfondendo, gli stili di connessione del tema chiaro nel seguente blocco di codice
collegano una proprietà personalizzata generica al colore specifico del tema chiaro. Ora tutti
gli utilizzi di var(--brand) utilizzeranno il colore chiaro del brand.
Tema chiaro (automatico)
: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);
}
Il sito ora utilizza il tema chiaro. Questo è un momento molto divertente e di successo. Vediamo altri esempi di utilizzo dei colori predefiniti in altri contesti di combinazioni di colori.
Tema scuro (automatico)
@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);
}
}
Tema chiaro
[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);
}
Tema scuro
[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);
}
Tema scuro
[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);
}
A questo punto, gli autori possono utilizzare i generici della combinazione di colori forniti in base alle necessità e non dovranno più preoccuparsi dei temi.
Conclusione
Ora che sai come ho fatto, come faresti tu? 🙂
Diversifichiamo i nostri approcci e impariamo tutti i modi per creare contenuti sul web. Crea un Codepen o ospita la tua demo, inviami un tweet e la aggiungerò alla sezione Remix della community di seguito.
Origine
Remix della community
- @chris-kruining ha aggiunto un cursore di tonalità,
colori di stato e modalità di contrasto per no-preference, more e less:
demo.