a new

alpha(), progress() e light-dark() per le immagini: cosa puoi togliere dal tuo CSS

Il riepilogo di settembre di web.dev mette tra le novità Baseline tre funzioni che toccano token, temi e fluidità. Cosa sostituiscono, dove si fermano e come usarle senza lasciare indietro i browser meno recenti.

5 min di lettura News · CSS

Aprendo il file dei token di un design system capita di trovare serie come --brand-10, --brand-20, --brand-50, create soltanto per avere lo stesso colore con trasparenze diverse. Capita anche di trovare due versioni di uno sfondo o di un logo, una per il tema chiaro e una per quello scuro, agganciate a un blocco @media (prefers-color-scheme: dark). Il 2 ottobre 2026 Rachel Andrew ha pubblicato su web.dev il riepilogo mensile delle funzionalità diventate "Baseline Newly available" a settembre, e tra queste ci sono tre funzioni CSS che intervengono proprio su questi punti: alpha(), light-dark() con valori immagine e progress().

La select personalizzabile, l'altra grande voce del riepilogo, l'ho già trattata in un articolo a parte. Qui mi concentro sulle tre funzioni che riguardano colore, temi e valori fluidi.

alpha(): la trasparenza derivata da un token

Secondo la definizione di web.dev, alpha() prende un colore di partenza e ne restituisce una versione con il canale alfa modificato, mantenendo i canali colore e lo spazio colore. MDN la descrive come una forma più breve della sintassi relativa dei colori. Il caso d'uso più diretto è dichiarare il colore una volta sola e ricavarne le varianti trasparenti:

CSS
:root {
  --brand: oklch(55% 0.22 270);
}

.overlay {
  background-color: alpha(from var(--brand) / 50%);
}

.card:hover {
  background-color: alpha(from var(--brand) / 40%);
}

MDN mostra anche la forma relativa: dentro calc() la parola chiave alpha rappresenta l'opacità del colore di partenza, quindi alpha(from var(--my-color) / calc(alpha * 0.5)) dimezza l'opacità di qualunque colore, anche se il token cambia.

Cosa si può togliere: le serie di token che differiscono soltanto per l'alfa, e le dichiarazioni che richiedevano di riscrivere il colore nella sintassi relativa per cambiare un solo canale. Il colore resta definito in un punto, e overlay, bordi e stati hover lo derivano.

Il supporto indicato da web.dev è Chrome ed Edge 151, Firefox 155 e Safari 27.

light-dark() accetta anche le immagini

Fino a poco fa light-dark() funzionava solo con i colori. Ora, scrive MDN, accetta due colori oppure due immagini e restituisce quella corrispondente allo schema attivo, senza bisogno della media feature prefers-color-scheme. Le immagini possono essere url(), gradienti e, in generale, i valori di tipo image di CSS:

CSS
:root {
  color-scheme: light dark;
}

.hero {
  background-image: light-dark(
    url("pattern-light.svg"),
    url("pattern-dark.svg")
  );
}

Ci sono tre condizioni da conoscere. La prima è che serve dichiarare color-scheme con entrambi i valori, altrimenti la funzione non ha uno schema da leggere. La seconda, ricordata da Bramus in un post del 19 marzo 2026 aggiornato a settembre, è che non si possono mescolare i tipi: due colori oppure due immagini, mai un colore e un'immagine nella stessa chiamata. La terza è una mia osservazione: la funzione lavora sui valori CSS, quindi copre sfondi, maschere e simili, ma non cambia la sorgente di un elemento img inserito nel markup.

Per verificare il supporto da CSS, il post di Bramus suggerisce @supports (background-image: light-dark(none, none)). Secondo web.dev i motori che la supportano sono Chrome ed Edge 150, Firefox 150 e Safari 27.

Cosa si può togliere: i blocchi @media (prefers-color-scheme: dark) che servono solo a cambiare un'immagine di sfondo, e con loro il rischio di dimenticarne uno quando si aggiunge un nuovo tema. Un vantaggio ricordato da MDN è che si può sovrascrivere color-scheme su singoli elementi, quindi una sezione sempre scura può avere le sue immagini senza regole speciali.

progress(): un numero tra 0 e 1

progress(valore, inizio, fine) restituisce la posizione del primo valore tra gli altri due, calcolata come (valore meno inizio) diviso (fine meno inizio). Per impostazione predefinita il risultato è limitato tra 0 e 1, e la parola chiave no-clamp permette di superare i limiti. L'esempio di web.dev lega l'opacità alla larghezza del viewport:

CSS
.card {
  opacity: progress(100vw, 320px, 1200px);
}

MDN precisa che i tre argomenti devono essere dello stesso tipo: tutti numeri, tutte lunghezze o tutte percentuali. Mescolare una lunghezza e un numero rende la dichiarazione non valida. Il valore ottenuto è un numero senza unità, quindi si può moltiplicare per altri valori, per esempio dentro calc(), per ricavare opacità, scale o componenti di un colore.

Non è una funzione per tutti i giorni. Ha senso quando una proprietà deve seguire in modo continuo la larghezza di un contenitore o del viewport e vuoi dichiarare una volta sola i due estremi, invece di ripetere gli stessi valori in più regole. Per i salti netti tra layout restano più adatte le media query e le container query. Il supporto indicato da web.dev è Chrome ed Edge 138, Firefox 155 e Safari 26.

Come adottarle senza lasciare indietro nessuno

Baseline "Newly available" significa che la funzione è disponibile nelle versioni correnti dei principali motori, non che sia presente in tutti i browser in circolazione. Le versioni elencate da web.dev sono recenti, e non ho dati sulla quota di utenti che le usa: va controllata sul traffico del tuo sito.

  • alpha(): Chrome ed Edge 151, Firefox 155, Safari 27.
  • light-dark() con immagini: Chrome ed Edge 150, Firefox 150, Safari 27.
  • progress(): Chrome ed Edge 138, Firefox 155, Safari 26.

Fonte dei numeri di versione: web.dev, 2 ottobre 2026.

C'è un dettaglio del CSS che conviene tenere presente. Se scrivi una dichiarazione di riserva e poi la versione nuova, un browser che non conosce la funzione scarta la riga nuova e usa la precedente. Ma se il valore contiene var(), il browser accetta la riga al momento del parsing e la scarta solo al calcolo, quando una dichiarazione precedente non può più subentrare. È un comportamento generale del CSS, non specifico di queste funzioni, e con alpha(from var(--brand) / 50%) può far restare senza colore un browser meno recente. In questi casi è più sicuro racchiudere la versione nuova in @supports:

CSS
.overlay {
  background-color: rgb(40 80 220 / 0.5); /* riserva */
}

@supports (background-color: alpha(from red / 50%)) {
  .overlay {
    background-color: alpha(from var(--brand) / 50%);
  }
}

Il test con @supports è una mia proposta e va provato nei browser che ti interessano prima di metterlo in produzione. Per light-dark() con le immagini vale lo stesso schema, con il test suggerito da Bramus.

Se devo scegliere da dove cominciare, parto da light-dark() con le immagini, perché elimina regole sparse e ha lo stesso numero di versione, 150, su Chrome, Edge e Firefox. Poi alpha(), quando il design system ha davvero token duplicati da ripulire. progress() la riservo ai casi in cui un valore deve seguire una larghezza con continuità.

Fonti

  1. web.dev, Rachel Andrew, “riepilogo mensile sulle novità della piattaforma web di settembre 2026”, 2 ottobre 2026
  2. MDN, “alpha()”
  3. MDN, “light-dark()”
  4. MDN, “progress()”
  5. Bramus, “More Easy Light-Dark Mode Switching: light-dark() is about to support images!”, 19 marzo 2026 (aggiornato)

Altri articoli

Contattami

1 / 4

Di cosa hai bisogno?

Non sono riuscito a inviare il messaggio. Riprova, o scrivimi direttamente a andrea.l.casiraghi@gmail.com.