Sintassi dei colori relativi CSS

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

Adam Argyle
Adam Argyle

In Chrome 119 è disponibile una funzionalità di colore molto potente del livello di colore CSS 5. La sintassi dei colori relativa crea un percorso agevole per la manipolazione dei colori all'interno del CSS, offrendo ai autori e ai designer la possibilità di:

Prima della sintassi dei colori relativa, per modificare l'opacità di un colore, devi creare proprietà personalizzate per i canali di un colore, in genere HSL, e assemblarli in un colore finale e in un colore della variante finale. Ciò significa gestire molti elementi di colore, il che può diventare rapidamente gravoso.

: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 la sintassi del colore relativa, puoi creare un colore del brand con qualsiasi spazio di colore o sintassi di cui hai bisogno e creare una variante con opacità a metà 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 dimostrare le manipolazioni di colore più comuni.

Se preferisci i video, quasi tutto l'articolo che segue è trattato in questa sfida della GUI.

Panoramica della sintassi

Lo scopo della sintassi dei colori relativi è consentire di ricavare un colore da un altro. Il colore di base è chiamato colore di origine ed è il colore che segue la nuova parola chiave from. Il browser convertirà e separerà questo colore originale e offrirà le parti come variabili da utilizzare nella nuova definizione di colore.

Viene mostrato un
diagramma della sintassi rgb(from green r g b / alpha), con una freccia
che parte dalla parte superiore del verde e si curva all'inizio della funzione rgb.
Questa freccia si divide in 4 frecce che poi rimandano alla relativa variabile. Le quattro frecce sono rosse, verdi, blu e alfa. Il rosso e il blu hanno un valore pari a 0, il verde è 128 e l'alfa è 100%.

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

Sebbene questa immagine mostri la suddivisione, il processo e le variabili, non cambia nemmeno il colore. Le variabili vengono reinserite nel colore invariato, pertanto il colore rimane verde.

La parola chiave from

La prima parte della sintassi da imparare è la parte from <color> oltre a specificare un colore. Viene visualizzato subito prima di specificare i valori. Ecco un esempio di codice in cui è stato aggiunto solo from green, subito prima della specifica dei valori per rgb().

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

La parola chiave from, se considerata come primo parametro nella notazione funzionale, trasforma la definizione di colore in un colore relativo. Dopo la parola chiave from, il CSS si aspetta un colore, un colore che ispirerà il colore successivo.

Conversione del colore

In termini più semplici, converte il verde nei canali r, g e b per utilizzarlo in 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 sintassi dei colori relativi sono un'accoppiata così vincente, perché puoi svelare il mistero del colore from. In genere, inoltre, 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 di colore che preferisci

Puoi scegliere lo spazio di colore con la notazione del colore 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 ha questo passaggio di conversione; il colore dopo from viene convertito nello spazio di colore specificato all'inizio del colore relativo. L'input e l'output non devono corrispondere, il che è molto liberatorio.

La possibilità di scegliere uno spazio di colore è anche un'opportunità, in quanto la scelta di uno spazio di colore tende a essere più incentrata sul tipo di alternanza di colore che su una preferenza. La preferenza si trova nei risultati, non nel formato di colore o nei tipi di canale. Questo concetto diventerà molto più chiaro nelle sezioni che mostrano i casi d'uso, poiché diversi spazi di colore eccellono in attività diverse.

Combina, abbina, ometti e ripeti le variabili

Un aspetto strano ma interessante di questa sintassi è che le variabili non devono 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 si trova dopo / 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% */

Utilizza calc() o altre funzioni CSS sulle variabili

Finora abbiamo creato il colore verde più e più volte. Imparare la sintassi, acquisire familiarità con i passaggi di conversione e destrutturazione. Ora è il momento di modificare le variabili, di alterare l'output in modo che non sia uguale all'input.

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

Ora è blu scuro. La tonalità è stata raddoppiata, passando da 120 a 240, alterando completamente il colore. In questo modo, la tonalità è stata ruotata lungo la ruota dei colori, un trucco interessante reso molto semplice con gli spazi di colore cilindrici come HSL, HWB, LCH e OKLCH.

Per visualizzare visivamente i valori dei canali, in modo da ottenere la matematica giusta senza indovinare o memorizzare le specifiche, prova questo strumento per i valori dei canali della sintassi di colore relativa. Mostra il valore di ciascun canale in base alla sintassi specificata, consentendoti di sapere esattamente quali valori hai a disposizione.

Verificare la disponibilità del supporto del browser

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

Casi d'uso e dimostrazioni

I seguenti esempi e casi d'uso hanno molte sintassi alternative per ottenere risultati simili o uguali. Le variazioni derivano dagli spazi di colore e dai canali che offrono.

Inoltre, molti esempi mostrano le regolazioni del colore con il linguaggio di by e to. Un colore modificato by è una modifica del colore relativa, una modifica che utilizza il valore della variabile e apporta una regolazione in base al suo valore corrente. Un colore cambiato to è una modifica assoluta del colore, una modifica che non utilizza il valore della variabile e specifica invece un valore completamente nuovo.

Tutte le demo sono disponibili in questa raccolta di Codepen.

Schiarire un colore

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

Schiarire di un valore

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. Questo spinge la luminosità del blu verso il bianco del 25%.

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

Schiarire a un valore specifico

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

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

Scurire un colore

Gli stessi spazi di colore efficaci per schiarire un colore sono ottimi anche per scurirlo.

Oscuramento di un determinato valore

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. Il colore blu si avvicina al nero del 25%.

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

Oscuramento fino a un valore specificato

Nell'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);
}

Saturazione di un colore

Saturazione per un importo

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

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

Saturazione a un valore specifico

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

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

Desatturo un colore

Desaturazione di un importo

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

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

Desaturazione a un valore specifico

Anziché applicare una saturazione ridotta in base a un valore, puoi applicarla a un valore specifico. L'esempio seguente .desaturate-to-25 crea un nuovo colore in base a indigo, ma imposta la saturazione su 25%.

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

Aumentare la crominanza di un colore

Questo effetto è simile alla saturazione di un colore, ma è diverso in alcuni modi. Innanzitutto, si tratta di una modifica chroma e non saturation, perché gli spazi colore che possono aumentare l'intervallo dinamico non utilizzano la saturazione. Gli spazi di colore che includono chroma supportano l'alta dinamica e consentono agli autori di aumentare la vivacità dei colori oltre il livello consentito dalla satura.

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

Regolare l'opacità di un colore

La creazione di una variante semitrasparente di un colore è uno degli aggiustamenti di colore più comuni eseguiti nei sistemi di progettazione. Se non l'hai visto, consulta l'esempio nell'introduzione di questo articolo, che illustra molto bene lo spazio dei problemi.

Regolare l'opacità di un importo

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

Regolare l'opacità su un valore specifico

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

Invertire un colore

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

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

Completare un colore

Se il tuo obiettivo non era invertire un colore, ma piuttosto completarlo, la rotazione della tonalità è probabilmente ciò che stai cercando. Scegli uno spazio di colore che offra la tonalità come angolo, quindi utilizza calc() per ruotarla di un'angolazione che preferisci. Per trovare il complementare di un colore, ruota di mezzo giro. In questo caso, puoi aggiungere o sottrarre 180 al canale h per ottenere il risultato.

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

Creare il contrasto con un colore

Come metodo per ottenere rapporti di contrasto dei colori accessibili, valuta L&midast; (Lstar). Viene utilizzato il canale di luminosità (L) (approssimativamente) uniforme per la percezione da LCH e OKLCH in un calc(). A seconda che tu abbia scelto come target un contrasto basso, medio o alto, il delta L&M è di circa 40, 50 o 60.

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

Contrastare un colore più scuro

La classe .well-contrasting-darker-color mostra L* con un delta di 60. Poiché il colore di origine è scuro (luminosità a basso valore), viene aggiunto il 60% (0,6) al canale Luminosità. Questa tecnica viene utilizzata per trovare un colore di testo scuro ben contrastante, della stessa tonalità, su uno sfondo chiaro.

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

Contrasta un colore più chiaro

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

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

Tavolozze dei colori

La sintassi dei colori relativi è molto utile per creare tavolozze di colori. È particolarmente utile e potente grazie al numero di spazi colore disponibili. I seguenti esempi utilizzano tutti OKLCH perché il canale di luminosità è affidabile e il canale di tonalità puoi essere ruotato senza effetti collaterali. L'esempio finale mostra una combinazione di aggiustamenti di luminosità e rotazione della tonalità per un risultato più interessante.

Apri il codice sorgente di esempio per queste e prova a modificare --base-color per vedere quanto sono dinamiche queste tavolozze. È divertente!

Se preferisci i video, su YouTube puoi trovare informazioni approfondite su come creare tavolozze di colori in CSS con OKLCH.

Tavolozze monocromatiche

Creare una tavolozza monocromatica significa creare una tavolozza con la stessa tonalità, ma con variazioni di luminosità e oscurità. Il colore centrale è il colore di origine per la tavolozza, dove su entrambi i lati sono posizionate due varianti più chiare e due più scure.

: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 una serie di tavolozze create con la sintassi dei colori relativa e OKLCH

Open Props, una libreria di variabili CSS senza costi, offre palette di colori create con questa strategia e le rende facilmente utilizzabili con un'importazione. Inoltre, sono tutti basati su un colore che puoi personalizzare. Devi solo scegliere un colore e verrà generata una tavolozza.

Tavolozze analoghe

Poiché la rotazione della tonalità è così facile con OKLCH e HSL, è semplicissimo creare una tavolozza di colori analoghi. Ruota la tonalità in base ai risultati che preferisci, modifica il colore di base e guarda come il browser crea nuove tavolozze.

: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 di colori triadici sono rotazioni di tonalità opposte ma armoniose in base a un colore di base. Se un colore complementare si trova sul lato opposto di un colore, come una linea retta tracciata al centro della ruota dei colori, le tavolozze triadiche sono come un triangolo di linee che trovano due colori ruotati in modo uguale da un colore di base. Per farlo, ruota la tonalità 120deg.

Si tratta di una lieve semplificazione della teoria del colore, ma è sufficiente per iniziare a utilizzare le tavolozze triadiche più complesse, se ti interessano.

: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 composte da quattro colori divisi equamente nella ruota dei colori, formando una tavolozza senza un valore dominante chiaro. Puoi anche pensare a due coppie di colori complementari. Se utilizzata con saggezza, può essere molto significativa.

Si tratta di una lieve semplificazione della teoria del colore, ma è sufficiente per iniziare a utilizzare le tavolozze tetradiche più complesse, se ti interessano.

: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));
}

Monocromatica con una leggera rotazione della tonalità

Molti esperti di colore hanno questo trucco a portata di mano. Il problema è che una scala di colori monocromatica può essere piuttosto noiosa. La soluzione consiste nell'aggiungere una rotazione della tonalità minore o maggiore a ogni nuovo colore man mano che la luminosità viene modificata.

Nell'esempio seguente, la luminosità di ogni campione viene diminuita del 10% e la tonalità viene ruotata di 10 gradi. Il risultato è una tavolozza che va dal rosa acceso all'indaco e sembra fondersi senza interruzioni, come farebbe 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 rotazione della tonalità

La seguente interfaccia della classifica utilizza questa strategia di rotazione della tonalità. Ogni elemento dell'elenco monitora il proprio indice nel documento come una variabile chiamata --i. Questo indice viene poi utilizzato per regolare crominanza, luminosità e tonalità. L'aggiustamento è solo del 5% o 5 gradi, molto più sottile rispetto all'esempio precedente con il colore rosa scuro, pertanto è necessario un occhio attento per notare il motivo per cui questa classifica può essere in qualsiasi tonalità con così eleganza.

Assicurati di modificare la tonalità nel cursore sotto la classifica e guarda come la sintassi dei colori relativa crea bellissimi momenti di colore.

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))
  );
}