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 consentire un concetto di scurimento o schiarimento del colore del brand, ad esempio del 20%, i 3 canali del valore del colore hsl devono essere estratti nelle rispettive proprietà personalizzate, come in questo caso:
* {
--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
Gli elementi essenziali di una combinazione di colori devono essere quelli del 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 al 10% di luminosità, mantiene la saturazione elevata al 100%,
in modo che il colore del brand possa ancora risaltare nel blu marino 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, sono i 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, abbasseremo 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 è aggregato 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 della luce in un unico posto
Non c'è bisogno di cercare in che modo i colori della luce vengono realizzati, tutti si trovano 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 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 si trovano al buio quando utilizzano questo tema, quindi esegui il test al buio.
- I colori devono essere desaturati in modo da non vibrare sullo schermo a causa della loro 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 scurire qualcosa che è già abbastanza scuro. È qui che --shadow-strength-dark
diventa particolarmente utile, perché ci consente di scurire le ombre modificando una variabile.
* {
--surface-shadow-dark: var(--brand-hue) 50% 3%;
--shadow-strength-dark: .8;
}
Controlla anche il livello di saturazione in quell'ombra. Riesci a notare il colore quando guardi l'interfaccia? Prova a rimuovere la saturazione da devtools, quale preferisci?
Tutti i colori scuri
* {
--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;
}
Attenuazione tema
Questa combinazione di colori si basa sull'orchestrazione di luminosità e saturazione. Deve essere presente una saturazione sufficiente per mantenere comunque una tonalità visibile, ma passare a malapena i punteggi di contrasto poiché si intende comunque attenuata e con contrasto basso.
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
Nota come la luminosità minima nel set di colori del testo scuro è pari al 65% e la maggiore luminosità nelle superfici scure è del 25%. cioè il 40% della stanza respiratoria tra di loro. Con il tema chiaro, la respirazione è del 55% in quello chiaro. Mantenere le differenze di luminosità tra i colori del testo e della superficie di circa il 40-50% può aiutare a mantenere elevati i rapporti di contrasto di colore, pur essendo un piccolo strumento per regolare se i punteggi sono scarsi.
Lo chiamo "bump bump til ya pass" (protuberanza fino al tuo passaggio), ovvero l'interazione di un valore di leggerezza fino a quando uno strumento indica che sto superando.
Ciascuno dei temi creati in questa sfida supera i punteggi di contrasto. La combinazione di colori attenuata presenta 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);
}
Ombra raduna
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
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 regolazioni di saturazione e oscurità, mentre l'intensità consente di aumentare facilmente l'intensità delle ombre quando si tratta di una combinazione di colori scuri. Il risultato finale era qualcosa del genere.
: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.
Analizzando gli stili connettivi del tema chiaro nel seguente blocco di codice,
collega una proprietà personalizzata generica al colore specifico del tema chiaro. Ora tutti
gli utilizzi di var(--brand)
utilizzeranno il colore del brand chiaro.
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 attenuato
[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 necessità e non devono 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.