Creazione di una combinazione di colori

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.

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.

anteprima dei risultati finali del tema chiaro

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;
}
screenshot dei colori della luce tutti insieme
Sandbox su CodePen

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:

  1. Gli utenti in genere non vedranno nulla quando utilizzano questo tema, quindi esegui i test al buio.
  2. I colori devono essere desaturati per non vibrare sullo schermo a causa di un'intensità eccessiva.

anteprima del risultato finale del tema scuro

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;
}
Screenshot dei colori scuri tutti insieme
Sandbox su CodePen

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.

anteprima dei risultati finali del tema scuro

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;
}
screenshot dei colori attenuati tutti insieme
Sandbox su CodePen

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.

MAIUSC + Freccia giù viene premuto per diminuire la luminosità e aumentare il contrasto fino a superare

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);
}
Screenshot delle combinazioni di superficie e testo attenuate
Screenshot delle combinazioni di testo e superficie scura con VisBug

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.

ogni ombra una accanto all'altra

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.