4 novembre 2026
Come adottare le novità CSS senza rischiare regressioni
Baseline, Can I Use, progressive enhancement e @supports: un metodo pratico per usare feature moderne senza “rompere” i layout.
Le feature CSS moderne arrivano in fretta, ma il supporto nei browser (e soprattutto su iOS) non è mai uniforme. In questo articolo vediamo come leggere correttamente Baseline, quando affidarsi a Can I Use, e come introdurre nuove funzionalità in modo sicuro con progressive enhancement, fallback a cascata e feature queries (@supports), inclusi i controlli sui selettori.
Nel 2026 CSS sta vivendo un’accelerazione continua: nuove proprietà, nuove funzioni, nuove pseudo-classi. Il problema non è “se” sono utili, ma come usarle senza trasformare la compatibilità in una roulette russa.
La buona notizia è che il CSS, per sua natura, offre già diversi strumenti per integrare feature moderne in modo graduale e robusto. La cattiva notizia è che serve un minimo di metodo: leggere bene lo stato di supporto, capire l’impatto di un’eventuale mancata compatibilità e scegliere la strategia giusta (fallback, @supports, build step, o attesa).
1) Baseline: utile, ma non è un via libera automatico
Negli ultimi tempi si è diffuso molto il riferimento a Baseline (iniziativa nata in ambito Chrome e oggi portata avanti dal gruppo WebDX). È una bussola comoda, ma non sostituisce il ragionamento.
In breve, gli stati principali sono:
- Baseline: limited availability: non è ancora presente in tutti i motori di rendering.
- Baseline: newly available: è presente in tutti i motori, ma da meno di 30 mesi.
- Baseline: widely available: è presente in tutti i motori da almeno 30 mesi.
Il punto critico: anche “widely available” non significa automaticamente “sicuro al 100% per il tuo pubblico”. Dipende da:
- Qual è l’ultimo browser che l’ha adottata (l’ordine di adozione influisce parecchio sulla copertura reale).
- Quali versioni sono effettivamente in uso nel tuo contesto (aziende, dispositivi vecchi, vincoli di aggiornamento).
- Stato e varianti della specifica: a volte il supporto è “sì, ma…” (flag, sintassi differenti, implementazioni parziali).
Baseline è ottimo per orientarsi, ma non basta come unica fonte decisionale.
2) Per decidere davvero: guarda la compatibilità “versione per versione”
Quando devi fare una scelta concreta (“posso spedirlo in produzione?”), serve dettaglio. Strumenti come Can I Use restano fondamentali perché mostrano:
- versioni specifiche supportate;
- feature dietro flag;
- note su implementazioni incomplete o differenze di sintassi;
- percentuali d’adozione globali/relative.
Occhio speciale a iOS
Molti team, più che guardare “browser generici”, ragionano in termini di versione iOS/Safari. Motivo:
- su iPhone, i browser sono vincolati al motore WebKit (di fatto, il comportamento è quello di Safari);
- su dispositivi vecchi può esserci un tetto massimo di aggiornamento, quindi una parte degli utenti non può “semplicemente aggiornare”.
Se il tuo prodotto ha traffico mobile significativo, iOS è spesso la variabile che decide quanto puoi spingerti.
3) Domanda guida: cosa succede se la feature non è supportata?
Questa è la domanda che separa le scelte sicure da quelle rischiose.
Il CSS ha un vantaggio enorme: se una dichiarazione non è riconosciuta, viene ignorata. Non “esplode” tutto come può succedere con JavaScript. Questo abilita naturalmente strategie di adozione progressiva.
Caso A — Se fallisce, non succede nulla di grave
Qui entra in gioco il progressive enhancement: aggiungi una piccola miglioria, e se manca il supporto l’esperienza resta accettabile.
Esempio tipico: un miglioramento tipografico come text-wrap: pretty.
- Browser moderni: paragrafi con spezzature più gradevoli.
- Browser non compatibili: testo normale, nessun layout rotto.
In questi casi, l’adozione è spesso a rischio quasi zero.
Caso B — Se fallisce, può degradare l’esperienza in modo evidente
Ci sono feature che, se non supportate, cambiano davvero il comportamento. Un esempio classico è quando introduci animazioni o transizioni “nuove” che rendono l’interazione più fluida, ma in fallback diventa istantanea.
Un caso interessante è l’abilitazione dell’animazione tra height: 0 e height: auto tramite:
:root {
interpolate-size: allow-keywords;
}
Se il browser non supporta questa capacità, non è che “si rompe tutto”: semplicemente l’apertura/chiusura può passare da animata a immediata.
Qui devi valutare:
- è accettabile che alcuni utenti vedano l’effetto “senza animazione”? spesso sì;
- il comportamento resta comprensibile e accessibile? deve essere sempre sì.
4) Fallback via cascata: dichiara due volte (nell’ordine giusto)
Quando la mancata compatibilità sarebbe problematica (es. colori, dove un valore non supportato potrebbe lasciare testo o sfondo non impostati), una strategia semplice è sfruttare la cascata:
.button {
background: #2f6feb; /* fallback */
background: oklch(55% 0.2 260); /* moderno */
}
- Se il browser capisce
oklch(), usa l’ultima dichiarazione. - Se non la capisce, ignora la riga e resta sul fallback.
È una tecnica banale ma estremamente efficace.
Automatizzare i fallback
Se non vuoi gestire manualmente questi doppioni, esistono strumenti che possono farlo nel build step (es. PostCSS, Lightning CSS), trasformando o affiancando sintassi moderne con fallback più compatibili.
5) Feature queries: @supports come cintura di sicurezza
Quando vuoi introdurre una feature moderna senza rischiare effetti collaterali, la soluzione più robusta è spesso @supports.
5.1) @supports con custom properties (pattern molto pratico)
Le custom properties accettano qualsiasi valore come “valido”, anche se poi non lo è nel punto in cui lo userai. Quindi per fare fallback puliti con variabili conviene usare @supports.
Esempio: vuoi una easing moderna, ma fallback su cubic-bezier().
:root {
--ease: cubic-bezier(.2, .8, .2, 1);
}
@supports (animation-timing-function: linear(0, 1)) {
:root {
--ease: linear(0, 1);
}
}
.card {
transition: transform 300ms var(--ease);
}
Così:
- dichiari una sola volta dove usi
--ease; - cambi il valore della variabile solo se la feature è supportata;
- eviti ripetizioni e riduci la probabilità di bug.
5.2) @supports per interi blocchi di layout (es. subgrid)
Ci sono casi in cui non basta un fallback “di valore”: vuoi proprio un layout alternativo.
subgrid è perfetto per questo approccio: puoi implementare un layout base funzionante ovunque, e migliorarlo dove disponibile.
.component {
display: grid;
grid-template-rows: auto auto 1fr;
}
@supports (grid-template-rows: subgrid) {
.component {
grid-template-rows: subgrid;
}
}
In questo modo eviti situazioni in cui, senza supporto, combinazioni di span e template possono generare risultati inattesi.
5.3) @supports può testare anche i selettori
Non tutti lo sfruttano, ma @supports può verificare la disponibilità di selettori tramite selector().
@supports selector(:has(*)) {
.list:has(.item--active) {
outline: 2px solid currentColor;
}
}
È un ottimo modo per usare selettori avanzati come “miglioria”, mantenendo un comportamento base per tutti.
6) Polyfill o attesa: quando ha senso
A volte la risposta giusta è:
- polyfill, ma con cautela: costo in performance, limiti tecnici, manutenzione;
- aspettare: alcune feature sono troppo recenti o troppo “DX-oriented” (pensiamo a funzionalità che cambiano soprattutto l’organizzazione del CSS, non l’output finale). In questi casi forzare l’adozione può creare più problemi che benefici.
Sintesi operativa
Un modo pragmatico per usare CSS moderno senza rompere nulla è questo:
- Valuta l’impatto del fallback: se non supportato, degrada bene?
- Verifica su Can I Use (e ragiona per versioni, soprattutto su iOS).
- Se è una “miglioria”, inseriscila direttamente (progressive enhancement).
- Se serve compatibilità certa, usa fallback in cascata o build tool.
- Se cambia layout o logica, proteggi con
@supports(anche per selettori).
La conseguenza pratica è potente: puoi adottare nuove feature quando ti danno un vantaggio reale, senza trasformare ogni release in una battaglia contro browser e dispositivi. CSS è già progettato per evolvere in questo modo; sta a noi usarne bene gli strumenti.