In breve
- Un tema con variabili CSS funziona meglio su due livelli: variabili di palette che contengono i colori grezzi e variabili semantiche che descrivono a cosa serve ogni colore.
- I componenti dovrebbero leggere solo variabili semantiche come --color-text o --color-surface, mai i valori della palette direttamente.
- La modalità scura diventa allora questione di puntare le variabili semantiche a valori diversi della palette, con una media query o un attributo data.
- La funzione light-dark() e la proprietà color-scheme permettono a una sola dichiarazione di contenere entrambe le modalità nei browser attuali.
- Un piccolo script inline nell'head che imposta il tema salvato prima del rendering della pagina evita il lampo del tema sbagliato.
In questa pagina
Un tema con variabili CSS è un insieme di proprietà personalizzate, come --color-surface e --color-text, che ogni componente legge al posto di colori scritti a mano. Per cambiare tema cambi le variabili, di solito su :root o su un attributo data-theme, e tutta l'interfaccia le segue. Il trucco che lo rende scalabile è dividere le variabili in due livelli: una palette di colori grezzi e ruoli semantici che puntano a quella palette.
Due livelli: palette e ruoli
Le variabili di palette prendono il nome da ciò che sono: --violet-600, --ink-900. Le variabili semantiche prendono il nome da ciò che fanno: --color-accent, --color-text-muted. I componenti leggono solo le seconde. Quando arriva la modalità scura, riassegni i ruoli e lasci intatti i componenti. È la stessa idea dei design token, espressa direttamente in CSS.
--violet-600: #7c3aedChi lo legge
Cambia quando
--color-accent: var(--violet-600)Chi lo legge
Cambia quando
Esempio
--button-bg: var(--color-accent)Chi lo legge
Cambia quando
:root {
/* Palette: raw values, named for what they are */
--paper-50: #faf8f5;
--paper-100: #f1ede6;
--ink-900: #14121f;
--ink-700: #3d3a4f;
--ink-500: #6b6880;
--violet-600: #6d28d9;
--violet-300: #c4b5fd;
--night-950: #0d0b16;
--night-900: #17142a;
--night-800: #221e3a;
/* Roles: what each colour is for (light mode) */
--color-bg: var(--paper-50);
--color-surface: var(--paper-100);
--color-text: var(--ink-900);
--color-text-muted: var(--ink-500);
--color-border: color-mix(in oklab, var(--ink-900) 12%, transparent);
--color-accent: var(--violet-600);
--color-on-accent: #ffffff;
}
body { background: var(--color-bg); color: var(--color-text); }
.card { background: var(--color-surface); border: 1px solid var(--color-border); }
.button { background: var(--color-accent); color: var(--color-on-accent); }Dare ai ruoli nomi che sopravvivono a un restyling
Il nome di un ruolo dovrebbe restare vero anche dopo che i colori cambiano. --light-grey smette di essere chiaro in modalità scura, e --blue mente il giorno in cui il brand diventa verde. Dai un nome al compito e all'abbinamento, così chi legge il foglio di stile dopo di te sa quale colore va su quale.
Nomi che si rompono
--blue,--purple-button--light-grey-bg--white-text--dark-border
Nomi che durano
--color-accent,--color-on-accent--color-surface--color-text--color-border
Aggiungere la modalità scura con le variabili CSS
La modalità scura riassegna i ruoli. Rispetta per impostazione predefinita la preferenza del sistema operativo e lascia che un attributo data-theme la sostituisca quando chi legge sceglie. Imposta anche color-scheme, così barre di scorrimento, controlli dei moduli e tela predefinita si adattano.
:root { color-scheme: light; }
/* Follow the system unless the reader picked light */
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) {
color-scheme: dark;
--color-bg: var(--night-950);
--color-surface: var(--night-900);
--color-text: #f2f0fa;
--color-text-muted: #a5a1bd;
--color-border: color-mix(in oklab, #ffffff 12%, transparent);
--color-accent: var(--violet-300);
--color-on-accent: var(--ink-900);
}
}
/* The reader picked dark explicitly */
:root[data-theme="dark"] {
color-scheme: dark;
--color-bg: var(--night-950);
--color-surface: var(--night-900);
--color-text: #f2f0fa;
--color-text-muted: #a5a1bd;
--color-border: color-mix(in oklab, #ffffff 12%, transparent);
--color-accent: var(--violet-300);
--color-on-accent: var(--ink-900);
}light-dark() elimina la ripetizione.La modalità scura non è la modalità chiara invertita. Le superfici si schiariscono man mano che salgono, gli accenti si illuminano e le ombre lasciano il posto ai bordi. Il design in modalità scura e i gradienti in modalità scura trattano l'aspetto visivo.
La scorciatoia light-dark()
I browser attuali supportano light-dark(), che prende un valore chiaro e uno scuro e ne sceglie uno in base al color-scheme dell'elemento. Imposta color-scheme: light dark sulla radice per seguire il sistema, oppure forza una modalità con l'attributo, e ogni ruolo diventa una sola riga: --color-bg: light-dark(var(--paper-50), var(--night-950)). Mantieni la forma più lunga se devi supportare browser precedenti al 2024.
Un selettore di tema che non lampeggia
Se la scelta salvata viene applicata dopo il rendering della pagina, chi ha scelto la modalità scura vede un lampo bianco a ogni caricamento. Imposta l'attributo in un minuscolo script inline nell'head, prima che qualsiasi foglio di stile dipinga il body.
<head>
<script>
(function () {
var saved = localStorage.getItem("theme");
if (saved === "light" || saved === "dark") {
document.documentElement.dataset.theme = saved;
}
})();
</script>
<link rel="stylesheet" href="/styles.css">
</head>dataset.theme e salvare il valore in localStorage.- 1
Offri tre scelte
Chiaro, scuro e sistema. Rimuovendo l'attributo il controllo torna a
prefers-color-scheme. - 2
Salva solo le scelte esplicite
Memorizza
lightodark; elimina la chiave per «sistema», così un cambiamento successivo nel sistema operativo viene rispettato. - 3
Evita le transizioni al caricamento
Se i colori hanno una transizione, abilitala solo dopo il primo rendering, altrimenti la pagina anima dal chiaro allo scuro mentre si carica.
Temi di brand oltre chiaro e scuro
Gli stessi due livelli gestiscono più brand in un solo codice. Ogni brand fornisce la propria palette e i propri valori dei ruoli sotto un attributo data-brand, e le modalità continuano a funzionare sopra. Con color-mix() puoi ricavare stati hover e tinte da un solo accento per brand, come mostrato in color-mix() in CSS.
[data-brand="harbour"] {
--color-accent: #0f766e;
--gradient-hero: linear-gradient(150deg, #042f2e 0%, #0f766e 55%, #5eead4 100%);
}
[data-brand="ember"] {
--color-accent: #c2410c;
--gradient-hero: linear-gradient(150deg, #431407 0%, #c2410c 55%, #fdba74 100%);
}
.button:hover { background: color-mix(in oklab, var(--color-accent), black 12%); }
.hero { background: var(--gradient-hero); }Poiché le proprietà personalizzate si ereditano, un tema non deve coprire l'intera pagina. Metti data-theme="dark" su una sola sezione, come una fascia promozionale o un footer, e tutto ciò che contiene legge i ruoli scuri mentre il resto della pagina resta chiaro. Scrivi il selettore scuro come [data-theme="dark"] invece di :root[data-theme="dark"] se vuoi che funzioni, e imposta color-scheme anche sulla sezione.
Web e design sulla stessa palette
Un tema in CSS è solo metà di un brand. Gli stessi colori dovrebbero comparire nei tuoi post social, nelle presentazioni e nelle email. Il brand kit di Gradiently contiene le tue palette, i loghi e i font per titoli e testo, e il Designer lo applica quando imposta un design, così il post che crei il lunedì usa lo stesso accento del tuo sito. Se stai ancora scegliendo quei colori, parti da come scegliere i colori del brand.
Le domande più frequenti
Come creo un tema con le variabili CSS?
Definisci variabili di palette con i colori grezzi, poi variabili semantiche come --color-bg che puntano a esse. I componenti leggono solo quelle semantiche e i temi le riassegnano.
Come aggiungo la modalità scura con le variabili CSS?
Sostituisci le variabili semantiche dentro @media (prefers-color-scheme: dark) e sotto un selettore [data-theme="dark"] per chi sceglie la modalità scura.
Come evito che il tema lampeggi al caricamento della pagina?
Leggi il tema salvato in un piccolo script inline nell'head e imposta l'attributo prima che il foglio di stile dipinga la pagina.
Cosa fa light-dark() in CSS?
Restituisce il primo valore in modalità chiara e il secondo in modalità scura, in base al color-scheme dell'elemento. Funziona nei principali browser attuali.
Posso salvare un gradiente in una variabile CSS?
Sì. Salva l'intero gradiente come valore e usalo in background. Per animare tra gradienti, registra i punti colore con @property.
Scritto da Gradiently
Il team dietro Gradiently, uno strumento di design costruito attorno ai Mark: gradienti vivi che fanno sembrare tuo tutto ciò che progetti.
Vedi il nostro profilo