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 degli utenti, mantenendo al contempo l'esperienza di creazione minima. Partiamo da un colore di base del brand e costruiamo un sistema di varianti: 2 colori di testo, 4 colori di superficie e un'ombra in tinta.
Questa guida inizia con la definizione di tutti i colori per ogni combinazione di colori. Solo alla fine vengono utilizzati per cambiare pagina.
Il brand
Spesso, un colore del brand è già stato stabilito e viene fornito come
hex o
rgb. Questa sfida della 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 applicare un concetto di scurimento o schiarimento del colore del brand, ad esempio del 20%, i tre canali del valore di colore HSL devono essere estratti nelle rispettive proprietà personalizzate, come segue:
* {
--brand-hue: 200;
--brand-saturation: 100%;
--brand-lightness: 50%;
}
CSS può eseguire operazioni matematiche su queste proprietà di colore, ad esempio calc(var(--brand-lightness) -
20%)
per ridurre il valore di luminosità del 20%. Questo è fondamentale per creare una combinazione di colori, in quanto il CSS può mantenere tutti i colori nella stessa famiglia di tonalità regolando la saturazione e la luminosità hsl.
Tema chiaro
Ogni variante di colore verrà contrassegnata con il relativo schema di corrispondenza. In questo caso, a ogni colore 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 calcoli:
* {
--brand-light: hsl(var(--brand-hue) var(--brand-saturation) var(--brand-lightness));
}
Colori testo
Inoltre, gli elementi essenziali di una combinazione di colori richiedono colori di testo. In un tema chiaro, il testo deve essere molto scuro. Nota che la luminosità dei seguenti colori è 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 con una luminosità del 10%, mantiene la saturazione elevata al 100% in modo che il colore del brand possa comunque trasparire nel blu scuro.
--text2-light
, non è scuro come il primo colore, il che è positivo perché è un colore secondario ed è anche molto meno saturo.
Colori delle superfici
I colori di superficie sono gli sfondi, i bordi e altre superfici decorative su cui o all'interno delle quali si trova il testo. In un tema chiaro, si tratta dei colori chiari, diversamente dai colori del testo che erano scuri. Per creare colori chiari con hsl, utilizzeremo valori percentuali più elevati nel terzo valore di luminosità. Inoltre, ridurremo la saturazione in modo che i grigi chiari non risultino 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 4 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, è consigliabile passare da --surface2-light
al passaggio del mouse su --surface3-light
, in modo che il passaggio del mouse aumenti il contrasto (da una luminosità del 99% a una del 92%, rendendo l'immagine più scura).
Ombre
Le ombre all'interno di una combinazione di colori sono di gran lunga superiori, ma aggiungono un aspetto realistico all'effetto e lo aiutano a distinguersi dalle ombre non realistiche basate sul nero. Per farlo, il colore dell'ombra utilizzerà la proprietà personalizzata della tonalità, sarà leggermente saturo con la tonalità, ma comunque molto scuro. In sostanza, crea un'ombra molto scura 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 componenti per eseguire i calcoli. Per saperne di più, vai alla sezione sull'ombra parabolica.
Colori chiari tutti insieme
Non è necessario cercare come vengono creati i colori chiari, poiché si trovano tutti in un unico punto del 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, solitamente più chiaro. Gli utenti, invece, scelgono spesso un tema scuro per diversi contesti, ad esempio la notte. Questi fattori mi hanno portato a tenere presenti due aspetti quando utilizzo temi scuri:
- In genere, gli utenti saranno al buio durante l'utilizzo di questo tema, quindi esegui il test al buio.
- I colori devono essere desaturati in modo da 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, mentre il tema scuro no. La saturazione viene dimezzata e la luminosità ridotta a un 50% relativo.
* {
--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ù simili al bianco.
* {
--text1-dark: hsl(var(--brand-hue) 15% 85%);
--text2-dark: hsl(var(--brand-hue) 5% 65%);
}
Colori delle superfici
In un tema scuro, i colori delle superfici devono essere scuri. I seguenti colori hanno luminosità e saturazione ridotte, con la prima superficie 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. È logico, perché è difficile attenuare qualcosa che è già abbastanza scuro. È qui che
--shadow-strength-dark
è 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, controlla la saturazione dell'ombra. Riesci a notare il colore quando guardi l'interfaccia? Prova a rimuovere la saturazione da devtools, 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. Deve essere presente una saturazione sufficiente per avere ancora una tonalità visibile, ma deve anche superare appena i punteggi di contrasto, poiché è pensato per essere scuro e avere un 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 delle superfici
* {
--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;
}
Applicare l'effetto sbiadimento a 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
Notare che la luminosità più bassa nel colore del testo scuro impostato è del 65% e la luminosità più elevata nelle superfici scure è del 25%. Il 40% di leggerezza tra loro. Nel tema chiaro, lo spazio di manovra è del 55%. Mantenere le differenze di luminosità tra i colori del testo e della superficie intorno al 40-50% può contribuire a mantenere elevati i rapporti di contrasto dei colori, oltre a essere un'opzione discreta da regolare nel caso in cui i punteggi siano scarsi.
Lo chiamo "bump bump til ya pass", ovvero l'interazione di aumento del valore di luminosità finché uno strumento non indica che sto passando.
Tutti i temi creati in questa sfida superano i punteggi di contrasto. La combinazione di colori sbiadita ha il contrasto più basso, ma soddisfa comunque i requisiti minimi. Per aiutare gli altri membri del team a utilizzare colori in contrasto, è buona norma creare un nome della classe che associ un colore della superficie a un colore di 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 lo strumento Ombra uniforme, che apprezzo molto. Ho preso lo snippet generato e l'ho personalizzato con i miei colori e i miei calcoli di opacità. Il motivo è che volevo 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à consente di aumentare facilmente l'intensità dell'ombra quando si utilizza una combinazione di colori scura. 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 volessi approfondire le ombre nella mia combinazione di colori, renderei costanti anche gli angoli delle ombre come token di design, poiché la direzione della luce dovrebbe essere la stessa tra tutte le ombre del design.
Utilizzo delle combinazioni di colori
Una volta completata la predefinizione dei colori, è il momento di trasformarli in proprietà indipendenti dallo schema. Voglio dire 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 semplificare il rispetto del tema.
Per farlo, l'utilizzo della combinazione di colori deve essere effettuato esclusivamente tramite le proprietà personalizzate generiche, che definiremo a breve. In questo modo,
gli utenti che utilizzano le variabili di progettazione non devono mai preoccuparsi di quale combinazione di colori sia
impostata al momento, ma devono solo utilizzare i colori della superficie e del testo. Invece di
color: var(--text1-light)
, utilizza color: var(--text1)
. Tutte le operazioni di adattamento e rotazione
degli colori vengono eseguite a un livello molto più elevato nel CSS.
Andando più a fondo, gli stili di collegamento 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. È un momento di grande soddisfazione. Vediamone altri mentre utilizziamo i nostri colori predefiniti in altri contesti di combinazione 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 sono liberi di utilizzare le combinazioni di colori generiche fornite in base alle proprie esigenze e non dovranno più preoccuparsi dei temi.
Conclusione
Ora che sai come ho fatto, come faresti? 🙂
Diversifichiamo i nostri approcci e impariamo tutti i modi per creare 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.