Un colore esadecimale e un colore rgb() sono gli stessi tre numeri scritti in due modi. #4F46E5 è semplicemente 79, 70, 229 in base 16: due cifre esadecimali per canale, ognuna capace di contenere da 0 a 255. Convertire tra i due è aritmetica. La parte interessante è cosa significhino davvero quei numeri, perché non è quello che quasi tutti presumono.
La forma breve raddoppia ogni cifra, non la riempie di zeri
L'esadecimale a tre cifre si espande ripetendo ogni carattere: #f00 diventa #ff0000, non #f00000. La regola esiste perché la forma breve copra l'intero intervallo: #fff deve essere bianco puro, e può esserlo solo se f diventa ff.
La conseguenza è che la forma breve non può esprimere la maggior parte dei colori. Sono raggiungibili solo 4.096 dei 16,7 milioni, perché ogni canale è limitato ai sedici valori 00, 11, 22 … ff. #4F46E5 non ha una forma a tre cifre. La forma breve è una comodità per i numeri tondi, non uno schema di compressione.
Il numero non è la luminosità — e questa è quella grossa
Ecco il fatto che sorprende quasi tutti, e che causa bug veri in design system veri. #808080 sta numericamente esattamente a metà tra #000000 e #FFFFFF. Non è a metà in luminosità. Emette circa il 21,6% della luce che emette il bianco.
Il motivo è che sRGB — lo spazio colore in cui vive ogni codice esadecimale del web — è codificato in gamma e non lineare. La codifica dedica deliberatamente più valori disponibili ai toni scuri, perché la vista umana è molto più sensibile alle differenze là sotto. Quindi i numeri sono spaziati percettivamente, non fisicamente. Il grigio che emette davvero metà della luce del bianco è attorno a #BCBCBC, che scritto così non somiglia per niente a un grigio "di mezzo".
La cosa conta nel momento in cui fai aritmetica sui colori. Fare la media di #000000 e #FFFFFF sommando i canali e dividendo per due dà #808080: un colore con il 21,6% della luminanza del bianco, presentato come se fosse il punto medio. La stessa operazione in spazio lineare dà #BCBCBC. È per questo che i gradienti ingenui tra colori saturi attraversano una banda scura e fangosa, per questo sfocare e ridimensionare immagini in spazio gamma le incupisce, e per questo del codice di blending che sembra ovviamente corretto produce risultati che sembrano sottilmente sbagliati.
Otto cifre, e cosa questo strumento non fa
Il CSS Color Module Level 4 ha aggiunto un canale alfa all'esadecimale: #RRGGBBAA, dove l'ultima coppia è l'opacità — #FF0000 80 è rosso al 50%. C'è anche una forma breve a quattro cifre, #RGBA, che si espande allo stesso modo. Tutti i browser attuali supportano entrambe.
Questo strumento gestisce sei cifre e tre, e si ferma lì: l'input è limitato a sette caratteri incluso il cancelletto. Se lavori con la trasparenza, rgba() o il moderno rgb(255 0 0 / 50%) separato da spazi è comunque la notazione più chiara, perché un'opacità scritta come coppia esadecimale è illeggibile per chiunque, te compreso tra sei mesi.
Entrambe le notazioni descrivono sRGB, e ormai è un limite
Un codice esadecimale non porta con sé nessuna informazione su quale spazio colore intenda; il web ha semplicemente concordato che sia sRGB, uno standard definito nel 1996 attorno alle capacità dei monitor a tubo catodico. Funzionava finché tutti gli schermi erano più o meno uguali. Funziona meno bene ora che la maggior parte di telefoni e portatili può mostrare una gamma di colori notevolmente più ampia.
È per questo che il CSS ha guadagnato funzioni colore come oklch() e color(display-p3 …). Possono esprimere colori saturi che nessun codice esadecimale raggiunge: un rosso più vivido di #FF0000. Se il rosso del tuo marchio sembra spento su un display moderno, è quello il soffitto che hai toccato, e nessuna regolazione di cifre esadecimali lo supererà. Per il lavoro quotidiano sulle interfacce, però, sRGB resta il denominatore comune sicuro, ed esadecimale resta il modo più corto di scriverlo.
Domande frequenti
Viene inviato qualcosa a un server?
No. Questo strumento è marcato "client": la conversione è qualche riga di aritmetica che gira nella scheda del tuo browser. Non viene trasmesso niente e non viene salvato niente.
Perché il punto medio tra due miei colori sembra sbagliato?
Quasi certamente il problema di gamma descritto sopra. Fare la media di valori esadecimali tratta i numeri sRGB come se fossero quantità di luce, e non lo sono: sono codificati percettivamente. Per fondere due colori correttamente, converti ogni canale in luce lineare, fai la media lì, poi riconverti. Oppure usa uno spazio colore pensato apposta: interpolare in Oklch dà risultati morbidi senza la banda fangosa, e il CSS ora lo supporta direttamente nei gradienti.
Meglio esadecimale o rgb()?
Sono identici in ciò che possono esprimere, quindi è una questione di leggibilità. L'esadecimale è più corto e domina negli strumenti di design, ed è per questo che la maggior parte dei codebase lo usa. rgb() è più facile da ragionare quando un valore viene da una variabile o da un calcolo, e la sintassi moderna rgb(255 0 0 / 50%) gestisce l'alfa in modo più leggibile di quanto un esadecimale a otto cifre farà mai. La coerenza dentro un codebase conta più della scelta in sé.
Il maiuscolo delle lettere conta?
No. #FF0000 e #ff0000 sono lo stesso colore per ogni parser. Il minuscolo è la convenzione più diffusa nel CSS ed è quello che producono la maggior parte dei formattatori; il maiuscolo è più comune negli strumenti di design. Scegline uno e lascia che sia un formattatore a imporlo, perché il maiuscolo misto in un codebase rende i colori più difficili da cercare di quanto abbia diritto di essere.
Come ottengo una versione più chiara o più scura di un colore?
Non moltiplicando i canali esadecimali, che è la mossa intuitiva e produce i risultati fangosi descritti sopra. Converti in HSL o, meglio, in Oklch, regola la luminosità e riconverti. Oklch vale la curva di apprendimento qui perché il suo asse di luminosità è percettivamente uniforme: aggiungere dieci punti di luminosità sembra lo stesso passo indipendentemente dalla tinta di partenza, che è esattamente ciò che serve a una scala di colori in un design system ed esattamente ciò che HSL non ti dà.