15 ottobre 2026

Immagini in dark mode senza media query: usare light-dark() in CSS

Una singola dichiarazione per gestire varianti chiare/scure (anche per background-image) e mantenere controllo sui componenti.

Gestire immagini diverse tra light e dark mode è sempre stato un punto dolente: CSS media query, duplicazioni e componenti difficili da “isolare”. Con la funzione CSS light-dark() oggi puoi scegliere due valori alternativi (chiaro/scuro) senza scrivere prefers-color-scheme, e in molti casi funziona anche con le immagini. Vediamo come applicarla, come “bloccare” una sezione in una specifica color scheme e quali attenzioni avere su ereditarietà e supporto browser.

Perché le immagini in dark mode sono sempre state scomode

Per colori e variabili, il passaggio tra light e dark mode è ormai routine. Le immagini, invece, spesso costringono ancora a:

  • duplicare regole con @media (prefers-color-scheme: dark);
  • mantenere asset separati e logiche “a rami”;
  • gestire componenti annidati in contesti diversi (un widget scuro dentro una pagina chiara, o viceversa).

Negli ultimi tempi CSS ha fatto un salto importante: light-dark() permette di scegliere tra due valori in base allo schema colore attivo, senza scrivere media query. E la parte interessante è che può essere usata anche con le immagini.


Il passaggio base: da prefers-color-scheme a light-dark()

Il modello mentale è semplice: invece di “se dark allora…”, dichiari direttamente cosa usare in light e cosa usare in dark.

Esempio tipico con colori:

:root {
  --bg: light-dark(#ffffff, #0b0d12);
  --text: light-dark(#111827, #e5e7eb);
}

body {
  background: var(--bg);
  color: var(--text);
}

Il sito seguirà automaticamente la preferenza dell’utente (o l’emulazione nei DevTools) senza bisogno della media query.


La svolta: light-dark() funziona anche con le immagini

Dove diventa davvero interessante è quando vuoi cambiare un’immagine (o un background) tra light e dark.

Per esempio, un hero con background diverso:

.hero {
  background-image: light-dark(
    url("/img/hero-light.jpg"),
    url("/img/hero-dark.jpg")
  );
  background-size: cover;
  background-position: center;
}

In pratica:

  • in light mode userai hero-light.jpg;
  • in dark mode userai hero-dark.jpg;
  • senza @media (prefers-color-scheme: dark).

Questo riduce duplicazioni e rende le regole molto più leggibili, soprattutto quando l’immagine è solo uno dei tanti dettagli che devono adattarsi.


“Bloccare” un componente in una color scheme specifica

Oltre al cambio automatico, c’è un altro aspetto utilissimo: puoi isolare una sezione e farle mantenere un certo schema colori anche quando il resto della pagina cambia.

Questo è particolarmente utile quando:

  • integri componenti riusabili in contesti diversi;
  • hai card/promobox con un look fisso;
  • vuoi garantire contrasto consistente indipendentemente dal tema globale.

Esempio: forzare una sezione a comportarsi come “dark”, anche se la pagina è in light mode.

.promo {
  color-scheme: dark;

  /* valori che reagiscono allo schema (che qui è forzato) */
  background-color: light-dark(#ffffff, #0b0d12);
  color: light-dark(#111827, #e5e7eb);

  background-image: light-dark(
    url("/img/promo-light.jpg"),
    url("/img/promo-dark.jpg")
  );
}

Con color-scheme: dark; stai dicendo al browser: questa porzione di UI deve ragionare come dark. E di conseguenza, light-dark() userà il valore scuro.

Attenzione: l’ereditarietà può sorprenderti

Se “blocchi” una sezione ma non imposti esplicitamente i colori del testo, potresti vedere comportamenti incoerenti. Il motivo è che:

  • il testo spesso eredita color dal body;
  • se il body cambia colore in base al tema, il testo dentro la sezione potrebbe cambiare anche se tu stai mantenendo uno sfondo/immagine scuri.

Soluzione: quando isoli un componente, dichiara anche i colori chiave (testo/sfondo/bordi) nello stesso contesto.


Supporto browser: cosa aspettarsi oggi

light-dark() ha ormai un supporto buono e, soprattutto, è disponibile nei principali motori moderni. Detto questo:

  • come funzione per i colori è mediamente più affidabile;
  • l’uso con immagini può essere leggermente meno uniforme (dipende dal browser e dalla versione).

In pratica: è una scelta sensata se stai lavorando con un target moderno e fai già uso di CSS recente. Se devi coprire ambienti più datati, valuta un fallback.


Sintesi operativa

  • Se stai ancora gestendo light/dark con @media (prefers-color-scheme: dark), light-dark() ti permette di semplificare e rendere più dichiarativo il CSS.
  • Puoi usare light-dark() anche per switchare asset grafici, inclusi i background.
  • Con color-scheme puoi isolare componenti e farli comportare come light o dark indipendentemente dal tema globale.
  • Quando “blocchi” una sezione, non dimenticare di impostare i colori del testo per evitare effetti collaterali dovuti all’ereditarietà.

La conseguenza pratica è un CSS più pulito, meno duplicato e più modulare: esattamente quello che serve quando i temi diventano parte strutturale del design system.