Sintassi dei colori relativi CSS

Creare nuovi colori in base ai canali e ai valori di un altro colore.

Adam Argyle
Adam Argyle

In Chrome 119 è una funzionalità colore molto potente di CSS Color Level 5. La sintassi del colore relativo crea un percorso fluido per la manipolazione del colore all'interno di CSS, offrendo ad autori e designer la possibilità di:

Prima della sintassi relativa del colore, per modificare l'opacità di un colore devi creare le proprietà personalizzate per i canali di un colore, di solito HSL, e assemblarli in un colore finale e un colore variante finale. Ciò significa gestire molti pezzi di colore, che possono diventare rapidamente gravosi.

:root {
  --brand-hue: 300deg;
  --brand-saturation: 75%;
  --brand-lightness: 50%;

  --brand-hsl:
    var(--brand-hue)
    var(--brand-saturation)
    var(--brand-lightness);

  --brand-color: hsl(var(--brand-hsl));

  /* all this work just so I can set the opacity to 50% in a variant */
  --brand-color-variant: hsl(var(--brand-hsl) / 50%);
}

Dopo una sintassi relativa al colore, puoi creare un colore per il brand con qualsiasi spazio colore o sintassi di cui hai bisogno e creare una variante con metà opacità con molto meno codice. È anche molto più facile leggere l'intento degli stili e del sistema.

:root {
  --brand-color: hsl(300deg 75% 50%);
  --brand-color-variant: hsl(from var(--brand-color) h s l / 50%);
}

Questo post ti aiuterà a imparare la sintassi e a mostrare le comuni manipolazioni dei colori.

Se preferisci i video, quasi tutti gli articoli seguenti sono trattati in questa GUI Challenge.

Panoramica della sintassi

L'obiettivo della sintassi relativa dei colori è consentire di ricavare un colore da un altro colore. Il colore di base è chiamato colore di origine ed è il colore che segue la nuova parola chiave from. Il browser convertirà e suddividerà questo colore di origine e offrirà le parti come variabili da utilizzare nella nuova definizione del colore.

Viene mostrato un
diagramma della sintassi rgb(dal verde r g b / alfa), con una freccia
che lascia la parte superiore di colore verde e che si incrocia verso l'inizio RGB della funzione.
Questa freccia si divide in 4 frecce che poi puntano alla rispettiva variabile. Le quattro frecce sono rosse, verdi, blu e alfa. Rosso e blu hanno il valore 0, verde è 128 e alfa è 100%.

Il diagramma precedente mostra il colore di origine green che viene convertito nello spazio colore del nuovo colore, trasformato in singoli numeri rappresentati come variabili r, g, b e alpha, che vengono quindi utilizzati direttamente come nuovi valori del colore rgb().

Questa immagine mostra ripartizione, processo e variabili, ma non cambia il colore. Le variabili vengono reintegrate nel colore invariato, quindi il colore verde diventa fisso.

La parola chiave from

La prima parte della sintassi da apprendere è la parte from <color>, aggiunta allo specificare un colore. immediatamente prima di specificare i valori. Ecco un esempio di codice in cui tutto quello che è stato aggiunto è from green, subito prima che vengano specificati i valori di rgb().

.syntax-introduction_same-colors {
  color: green;
  color: rgb(0 128 0);
  color: rgb(from green r g b);    /* result = rgb(0 128 0) */
}

Quella parola chiave from, se vista come il primo parametro nella notazione funzionale, trasforma la definizione del colore in un colore relativo. Dopo la parola chiave from, il CSS prevede un colore, ossia un colore che ispira il colore successivo.

Conversione del colore

In termini più semplici, converte il verde in canali r g e b per utilizzarli con un nuovo colore.

rgb(from green r g b)           /* r=0 g=128 b=0 */
rgb(from rgb(0 128 0) r g b);   /* r=0 g=128 b=0 */

Colori delle proprietà personalizzate

La lettura di rgb from green è molto chiara e facile da capire. Ecco perché le proprietà personalizzate e la relativa sintassi dei colori sono un ottimo abbinamento, perché puoi eliminare il mistero del colore from. Inoltre, in genere non è necessario conoscere il formato del colore della proprietà personalizzata, poiché stai creando un nuovo colore in un formato a tua scelta.

rgb(from rgb(255 105 180) r g b) /* ????? */
rgb(from var(--hotpink) r g b)   /* clear */

Lavora nello spazio colore che preferisci

Puoi scegliere lo spazio colore con la notazione dei colori funzionale che preferisci.

rgb(from hsl(120 100% 25%) r g b)     /*  r=0   g=128  b=0    */
hsl(from hsl(120 100% 25%) h s l)     /*  h=120 s=100% l=25%  */
hwb(from hsl(120 100% 25%) h w b)     /*  h=120 w=0%   b=50%  */
lch(from hsl(120 100% 25%) l c h)     /*  l=46  c=68   h=134  */

La sintassi del colore relativo include questo passaggio di conversione; il colore dopo from viene convertito nello spazio colore come specificato all'inizio del colore relativo. L'input e l'output non devono necessariamente corrispondere, il che è molto liberatorio.

Anche la possibilità di scegliere uno spazio colore è molto utile, dato che la scelta di uno spazio colore tende a essere più focalizzata sul tipo di alternanza dei colori che su una preferenza. La preferenza risiede nei risultati, non nel formato di colore o nei tipi di canali. Questo diventerà molto più chiaro nelle sezioni che dimostrano i casi d'uso, poiché spazi di colore diversi si adattano ad attività diverse.

Mescola, abbina, ometti e ripeti le variabili

Questa sintassi presenta elementi strani ma molto interessanti: le variabili non devono necessariamente essere riordinate e possono essere ripetute.

rgb(from green g g g)    /* rgb(128 128 128) */
rgb(from green b r g)    /* rgb(0 0 128) */
rgb(from green 0 0 g)    /* rgb(0 0 128) */

Opacità come variabile

La sintassi fornisce anche l'opacità come variabile denominata alpha. È facoltativo e segue / nella notazione dei colori funzionali.

rgb(from #00800080 r g b / alpha)             /* alpha=50% */
rgb(from rgba(0,128,0,.5) r g b / alpha)      /* alpha=50% */
rgb(from rgb(0 128 0 / 50%) r g b / alpha)    /* alpha=50% */

Utilizzare calc() o altre funzioni CSS sulle variabili

Finora abbiamo continuato a creare il colore verde. Imparare la sintassi, acquisire familiarità con i passaggi di conversione e destrutturazione. Ora è il momento di modificare le variabili e l'output in modo che non corrisponda all'input.

green                              /*  h=120 s=100% l=25%  */
hsl(from green calc(h * 2) s l)    /*  h=240 s=100% l=25%  */

È blu marino ora! La tonalità è stata raddoppiata, assumendo una tonalità 120 e poi trasformandola in 240, alterando completamente il colore. In questo modo, la tonalità è stata ruotata lungo la ruota dei colori, un trucco semplice e semplice grazie agli spazi colore cilindrici come HSL, HWB, LCH e OKLCH.

Per vedere visivamente i valori dei canali, in modo da comprendere in modo corretto le operazioni matematiche senza dover tirare a indovinare o a memorizzare le specifiche, prova questo strumento per i valori relativi ai canali di sintassi relativi ai colori. Rivela il valore di ogni canale in base alla sintassi specificata, consentendoti di sapere esattamente con quali valori hai a disposizione.

Verificare il supporto del browser

@supports (color: rgb(from white r g b)) {
  /* safe to use relative color syntax */
}

Casi d'uso e dimostrazioni

Gli esempi e i casi d'uso che seguono hanno molte sintassi alternative per ottenere risultati simili o uguali. Le variazioni provengono dagli spazi cromatici e dai canali che offrono.

Inoltre, molti esempi mostrano le regolazioni del colore con la formulazione di by e to. Una modifica di colore by è una variazione di colore relativa: una modifica che utilizza il valore della variabile e apporta una correzione in base al suo valore corrente. Un colore to modificato è una modifica assoluta del colore, ovvero una modifica che non utilizza il valore della variabile, ma specifica un valore completamente nuovo.

Tutte le demo sono disponibili in questa raccolta Codepen.

Schiarire un colore

Gli spazi colore OKLCH, OKLAB, XYZ o sRGB forniscono i risultati più prevedibili quando schiari i colori.

Schiarisci di una quantità

Nell'esempio seguente .lighten-by-25 prende il colore blue e lo converte in OKLCH, quindi schiarisce il blu aumentando il canale l (luminosità) moltiplicando il valore corrente per 1.25. In questo modo, la luminosità blu spinge il bianco verso il bianco del 25%.

.lighten-by-25 {
  background: oklch(from blue calc(l * 1.25) c h);
}

Schiarire a un valore specifico

L'esempio seguente .lighten-to-75 non utilizza il canale l per alleggerire blue, ma sostituisce completamente il valore con 75%.

.lighten-to-75 {
  background: oklch(from blue 75% c h);
}

Scurire un colore

Gli stessi spazi cromatici efficaci nell'schiarire un colore sono ideali anche per scurire i colori.

Scurisci di una quantità

Nell'esempio seguente, .darken-by-25 prende il colore blu e lo converte in OKLCH, quindi scurisce il blu diminuendo il canale l (luminosità) del 25% moltiplicando il valore per .75. In questo modo il colore blu spinge il nero verso il nero del 25%.

.darken-by-25 {
  background: oklch(from blue calc(l * .75) c h);
}

Scurire in base a un valore specificato

L'esempio seguente .darken-to-25 non utilizza il canale l per scurire blue, ma sostituisce completamente il valore con 25%.

.darken-to-25 {
  background: oklch(from blue 25% c h);
}

Saturare un colore

Satura di una quantità

L'esempio seguente, .saturate-by-50, utilizza il valore s di hsl() per aumentare la vivacità di orchid di un valore 50% relativo.

.saturate-by-50 {
  background: hsl(from orchid h calc(s * 1.5) l);
}

Saturare a una quantità specifica

L'esempio seguente .saturate-to-100 non utilizza il canale s di hsl(), ma specifica un valore di saturazione desiderato. In questo esempio, la saturazione è aumentata a 100%.

.saturate-to-100 {
  background: hsl(from orchid h 100% l);
}

Desaturare un colore

Desaturazione di una quantità

L'esempio seguente .desaturate-by-half utilizza il valore s di hsl() per dimezzare la saturazione di indigo.

.desaturate-by-half {
  background: hsl(from indigo h calc(s / 2) l);
}

Desaturare in base a un valore specifico

Anziché desaturare di una certa quantità, puoi desaturare a un valore desiderato specifico. L'esempio seguente .desaturate-to-25 crea un nuovo colore basato su indigo ma imposta la saturazione al 25%.

.desaturate-to-25 {
  background: hsl(from indigo h 25% l);
}

Aumento della crominanza di un colore

Questo effetto è simile alla saturazione di un colore, ma in un paio di modi è diverso. Innanzitutto, si tratta di una modifica di chroma e non di saturation, perché gli spazi colore che possono essere aumentati in un intervallo dinamico elevato non utilizzano la saturazione. Gli spazi colore che presentano chroma supportano l'elevata gamma dinamica, che consente agli autori di aumentare la brillantezza dei colori oltre la saturazione.

.increase-chroma {
  background: oklch(from orange l calc(c + .1) h);
}

Regola l'opacità di un colore

La creazione di una variante semitrasparente di un colore è una delle regolazioni più comuni del colore effettuate nei sistemi di progettazione. Guarda l'esempio nell'introduzione di questo articolo, se ti è sfuggito, delinea molto bene lo spazio problematico.

Regola l'opacità di una quantità

.decrease-opacity-by-25 {
  background: rgb(from lime r g b / calc(alpha / 2));
}

Regola l'opacità in base a un valore specifico

.decrease-opacity-to-25 {
  background: rgb(from lime r g b / 25%);
}

Inverti un colore

L'inversione dei colori è una funzione di regolazione dei colori comune presente nelle librerie dei colori. Un modo per farlo è convertire un colore in RGB e sottrarre il valore di ciascun canale da 1.

.invert-each-rgb-channel {
  background: rgb(from yellow calc(255 - r) calc(255 - g) calc(255 - b));
}

Abbina un colore

Se il tuo obiettivo non era invertire un colore ma piuttosto completarlo, la rotazione della tonalità sarebbe probabilmente ciò che stai cercando. Scegli uno spazio colore che offra la tonalità come angolo, quindi usa calc() per ruotare la tonalità di una quantità che preferisci. La ricerca del complemento di un colore viene eseguita ruotando di mezzo giro; in questo caso, puoi aggiungere o sottrarre dal canale h di 180 per ottenere il risultato.

.complementary-color {
  background: hsl(from blue calc(h + 180) s l);
}

Contrastare un colore

Come metodo per ottenere rapporti di contrasto di colore accessibili, considera L&midast; (Lstar). Viene utilizzato il canale di leggerezza percepitamente uniforme (L) di LCH e OKLCH, in un calc(). A seconda di come scegli come target il contrasto basso, medio o alto, il delta L/midast è di circa 40, ~50 o ~60.

Questa tecnica funziona bene con qualsiasi tonalità di LCH o OKLCH.

Contrastare un colore più scuro

La classe .well-contrasting-darker-color dimostra L* con un delta di 60. Poiché il colore di origine è un colore scuro (luminosità di basso valore), al canale di luminosità viene aggiunto il 60% (0,6). Questa tecnica consente di trovare un colore del testo scuro, con la stessa tonalità su uno sfondo chiaro.

.well-contrasting-darker-color {
  background: darkred;
  color: oklch(from darkred calc(l + .60) c h);
}

Contrastare un colore più chiaro

La classe .well-contrasting-lighter-color dimostra anche L* con un delta del 60%. Poiché il colore di origine è un colore chiaro (luminosità di alto valore), 0,60 viene sottratto dal canale di luminosità.

.well-contrasting-lighter-color {
  background: lightpink;
  color: oklch(from lightpink calc(l - .60) c h);
}

Tavolozze dei colori

La sintassi dei colori relativa è ottima nella creazione delle tavolozze dei colori. È particolarmente utile e potente, per via del numero di spazi colore disponibili. Gli esempi riportati di seguito utilizzano tutti OKLCH perché il canale di luminosità è affidabile e il canale di tonalità può essere ruotato senza effetti collaterali. L'esempio finale mostra una combinazione di regolazioni della rotazione della tonalità e della luminosità per un risultato più interessante.

Apri il codice sorgente di esempio e prova a modificare --base-color, per vedere quanto sono dinamiche le tavolozze. Divertente!

Se ti piacciono i video, ti do informazioni dettagliate sulla creazione delle tavolozze dei colori in CSS con OKLCH su YouTube.

Tavolozze monocromatiche

Creare una tavolozza monocromatica consiste nel creare una tavolozza con la stessa tonalità, ma con variazioni di luminosità e oscurità. Il colore centrale è il colore di origine della tavolozza, dove vengono applicate due varianti più chiare e due più scure su entrambi i lati.

:root {
  --base-color: deeppink;

  --color-0: oklch(from var(--base-color) calc(l + .20) c h); /* lightest */
  --color-1: oklch(from var(--base-color) calc(l + .10) c h);
  --color-2: var(--base-color);
  --color-3: oklch(from var(--base-color) calc(l - .10) c h);
  --color-4: oklch(from var(--base-color) calc(l - .20) c h); /* darkest */
}
Prova diverse tavolozze realizzate con la relativa sintassi dei colori e OKLCH

Open Props, una libreria di variabili CSS senza costi, offre tavolozze dei colori create con questa strategia e le rende facilmente utilizzabili con un'importazione. Inoltre, sono realizzati con un colore personalizzabile, basta scegliere un colore per creare una tavolozza.

Tavolozze analoghe

Poiché la rotazione delle tonalità è estremamente semplice con OKLCH e HSL, non è facile creare una tavolozza di colori analogica. Ruota la tonalità di una quantità che ti soddisfa i risultati e modifica il colore di base e osserva le nuove tavolozze create dal browser.

:root {
  --base-color: blue;

  --primary:   var(--base-color);
  --secondary: oklch(from var(--base-color) l c calc(h - 45));
  --tertiary:  oklch(from var(--base-color) l c calc(h + 45));
}

Tavolozze triadiche

Analogamente ai colori complementari, le tavolozze dei colori triadici sono opposte, ma armoniose, a seconda del colore di base. Se un colore complementare si trova sul lato opposto di un colore, ad esempio una linea retta tracciata al centro della ruota dei colori, le tavolozze triadiche sono come un triangolo di linee, in modo che due colori ruotano equamente rispetto a un colore di base. A questo scopo, ruota la tonalità 120deg.

Si tratta di una leggera semplificazione della teoria dei colori, ma è sufficiente per iniziare a utilizzare le tavolozze triadiche più complesse, se ti interessa.

:root {
  --base-color: yellow;
  --triad-1: oklch(from var(--base-color) l c calc(h - 120));
  --triad-2: oklch(from var(--base-color) l c calc(h + 120));
}

Tavolozze tetradiche

Le tavolozze tetradiche sono quattro colori distribuiti uniformemente intorno alla ruota dei colori, creando una tavolozza senza un valore dominante chiaro. Potresti pensare anche a questo prodotto come a due paia di colori complementari. Se usata saggiamente, può essere molto significativa.

Questa è una leggera semplificazione della teoria dei colori, ma è sufficiente per iniziare a utilizzare le tavolozze tetradiche più complesse, se ti interessa.

:root {
  --base-color: lime;

  --color-1: var(--base-color);
  --color-2: oklch(from var(--base-color) l c calc(h + 90));
  --color-3: oklch(from var(--base-color) l c calc(h + 180));
  --color-4: oklch(from var(--base-color) l c calc(h + 270));
}

Monocromatico con leggera rotazione delle tonalità

Molti esperti di colore si avvalgono di questo trucco. Il problema è che una scala dei colori monocromatici può essere piuttosto noiosa. La soluzione consiste nell'aggiungere una rotazione della tonalità minore o maggiore a ogni nuovo colore quando la luminosità cambia.

L'esempio seguente riduce la luminosità del 10% per ogni campione e ruota anche la tonalità di 10 gradi. Il risultato è una tavolozza dai rosa acceso al blu indaco che sembra fondersi senza intoppi come un gradiente.

:root {
  --base-color: deeppink;

  --color-1: var(--base-color);
  --color-2: oklch(from var(--base-color) calc(l - .10) c calc(h - 10));
  --color-3: oklch(from var(--base-color) calc(l - .20) c calc(h - 20));
  --color-4: oklch(from var(--base-color) calc(l - .30) c calc(h - 30));
  --color-5: oklch(from var(--base-color) calc(l - .40) c calc(h - 40));
}
Prova questa classifica creata con OKLCH e la rotazione delle tonalità

La seguente interfaccia leaderboard utilizza questa strategia di rotazione tonalità. Ogni elemento dell'elenco monitora il proprio indice nel documento come una variabile denominata --i. che viene quindi utilizzato per regolare la crominanza, la leggerezza e la tonalità. L'aggiustamento è solo del 5% o di 5 gradi, molto più sottile dell'esempio sopra riportato con il deeppink, quindi è bene avere con attenzione il motivo per cui questo leaderboard può essere in qualsiasi tonalità con tale eleganza.

Non dimenticare di modificare la tonalità del cursore sotto la classifica e di vedere la relativa sintassi dei colori consente di creare splendidi momenti cromatici.

li {
  --_bg: oklch(
    /* decrease lightness as list grows */
    calc(75% - (var(--i) * 5%))

    /* decrease chroma as list grows */
    calc(.2 - (var(--i) * .01))

    /* lightly rotate the hue as the list grows */
    calc(var(--hue) - (var(--i) + 5))
  );
}