Come aggiungere la dark mode a un sito web (CSS, Tailwind, Next.js)
Come aggiungere la dark mode a un sito web
Come aggiungere la dark mode: CSS, Tailwind e Next.js | We.Inc
Aggiungi la dark mode con prefers-color-scheme, variabili CSS e light-dark(), un selettore Chiaro/Scuro/Sistema, Tailwind v4 e next-themes, senza flash al caricamento.
La dark mode più semplice è solo CSS: dichiara color-scheme: light dark, tieni i colori in custom property e scambiali dentro @media (prefers-color-scheme: dark). Per un selettore manuale, imposta una classe o un attributo data sull'elemento html, salva la scelta in localStorage e applicala con un piccolo script inline nella head, così il tema sbagliato non lampeggia mai.
Quale approccio si adatta al tuo stack
Stack
Segue il sistema operativo
Selettore manuale
Elemento chiave
CSS puro
Sì
No
@media (prefers-color-scheme: dark)
CSS + piccolo script
Sì
Sì
data-theme su html + script inline nella head
Tailwind CSS v4
Sì, per impostazione predefinita
Con @custom-variant
utility dark:
Next.js App Router
Sì
Sì
ThemeProvider di next-themes
La dark mode ha tre parti in movimento: colori che possono cambiare, un modo per decidere quale set usare e un tempismo che fa disegnare correttamente la pagina fin dalla prima volta. L'anteprima qui sotto ti permette di passare tra chiaro, scuro e sistema su un layout di esempio, poi ogni sezione ti dà il codice esatto per CSS puro, Tailwind e Next.js.
Scegli Chiaro, Scuro o Sistema nell'anteprima. Sistema segue il tuo sistema operativo e si aggiorna dal vivo se lo cambi.
Nota che anche il campo del modulo e la barra di scorrimento cambiano. È la proprietà color-scheme al lavoro.
Scegli il tuo stack tra gli esempi qui sotto e copia il codice. Lo script anti-flash va inline nella head.
Prova ricaricando in ogni modalità, e una volta con il sistema operativo impostato su scuro e nulla di salvato.
Non limitarti a invertire nero puro su bianco puro. Grigi scuri leggermente più chiari con testo bianco sporco si leggono meglio a lungo.
Ricontrolla il contrasto in entrambi i temi. Un blu del brand che supera il test su bianco può fallirlo su uno sfondo grigio scuro.
Dai a immagini e loghi una variante scura, o uno sfondo trasparente, così un riquadro bianco non risplende su una pagina scura.
Salva l'opzione sistema come assenza di un valore salvato invece che come parola, così un cambio successivo del sistema operativo viene ancora seguito.
Aggiungi <meta name="color-scheme" content="light dark"> così il browser disegna uno sfondo scuro prima che arrivi il tuo CSS.
Domande frequenti
Come evito il flash bianco quando la pagina si carica in dark mode?
Decidi il tema prima del primo rendering. Metti un piccolo script bloccante in cima alla head che legge la scelta salvata e la preferenza di sistema e imposta la classe o l'attributo sull'elemento html. Gli script alla fine del body o dentro un componente del framework vengono eseguiti troppo tardi.
Come funziona la dark mode in Tailwind?
In Tailwind v4 la variante dark: usa prefers-color-scheme per impostazione predefinita, quindi dark:bg-gray-900 si applica quando il sistema è scuro. Per controllarla con un selettore, aggiungi @custom-variant dark (&:where(.dark, .dark *)); al tuo CSS e metti la classe dark sull'elemento html.
Come aggiungo la dark mode in Next.js?
La strada comune è il pacchetto next-themes con licenza MIT. Avvolgi l'app nel suo ThemeProvider dentro il root layout, aggiungi suppressHydrationWarning al tag html e chiama setTheme da useTheme in un client component. Inserisce lui lo script anti-flash per te.
Cosa fa color-scheme?
Dice al browser quali schemi supporta la tua pagina, così le parti integrate come i controlli dei moduli, le barre di scorrimento e lo sfondo della pagina usano colori coerenti. Impostare color-scheme: light dark sulla radice è anche necessario perché la funzione light-dark() scelga il suo secondo valore.
La dark mode deve seguire il sistema o avere un selettore?
Entrambe le cose. Usa come predefinita la preferenza di sistema, perché le persone l'hanno già scelta, e offri un selettore con Chiaro, Scuro e Sistema così un visitatore può sovrascriverla solo per il tuo sito.
Costruisci prima la palette con le variabili
Dai nomi ai colori in base al ruolo, non all'aspetto: --bg, --surface, --text, --muted, --accent, --border. I componenti usano sempre e solo quei nomi. Cambiare tema significa così ridefinire una manciata di variabili in un solo punto.
La funzione light-dark() accorcia ancora di più il tutto tenendo entrambi i valori in una sola dichiarazione. MDN la indica come Baseline 2024, quindi tieni un fallback per i browser più vecchi se il tuo pubblico ne ha bisogno.
Rendere accessibile il selettore
Un selettore è un vero pulsante con un nome chiaro. Per un interruttore a due stati usa aria-pressed; per tre scelte un piccolo gruppo di radio button o un select è più chiaro di un'icona che cicla.
Non annunciare nulla in più. Il cambiamento visibile è il feedback, e lo stato del controllo dice agli utenti di screen reader cosa è selezionato.
Rendering lato server e idratazione
Un server non può conoscere il tema di un visitatore alla prima richiesta, quindi l'HTML generato non può includere testo legato al tema come Passa al chiaro. Mostra l'etichetta del selettore solo dopo che il componente è montato, oppure mostra qualcosa di neutro.
È anche per questo che next-themes chiede suppressHydrationWarning su html: il suo script cambia lì un attributo prima che React esegua l'idratazione.
1. CSS puro che segue il sistema
Variabili scambiate da prefers-color-scheme
Il riquadro del risultato segue l'impostazione del tuo dispositivo. Imposta il sistema su scuro e si aggiorna senza ricaricare.
La stessa idea con light-dark()
Una dichiarazione per colore. Richiede color-scheme sulla radice, e MDN la indica come Baseline 2024.
2. Un selettore Chiaro, Scuro e Sistema senza flash
Script inline in cima alla head
Viene eseguito prima che il body venga disegnato. Se non c'è nulla di salvato non fa niente, così la media query continua a seguire il sistema.
CSS che rispetta sia l'attributo sia il sistema
L'attributo vince quando è presente. Senza di esso decide la media query.
Il selettore vero e proprio
Un select con tre opzioni. Scegliere Sistema rimuove il valore salvato.
3. Tailwind CSS v4
Utility dark: con un selettore a classe
Senza la riga @custom-variant, dark: segue prefers-color-scheme. Con quella riga, la classe dark su html controlla il tema.
4. Next.js App Router con next-themes
Root layout e un provider client
ThemeProvider è un client component, quindi sta in un file a parte. attribute="class" lo collega alla classe dark di Tailwind.
Selettore che aspetta di essere montato
Il server non conosce il tema, quindi il controllo viene mostrato dopo il montaggio per evitare un errore di idratazione.
Anteprima del tema
Passa tra Chiaro, Scuro e Sistema per vedere cambiare un layout di esempio, compresi i suoi controlli dei moduli.
Tema
Chiaro
Scuro
Sistema (ora scuro)
Sistema (ora chiaro)
Forno del Porto
Esempio
Menu
Vieni a trovarci
Sfornato alle 7
Pane a lievitazione naturale, di segale e ai semi ogni mattina.