Le animazioni scroll-driven CSS (animation-timeline: view()) sono una tecnologia potente, ma non ancora supportata da tutti i browser. Safari ha un supporto parziale, Firefox è ancora in fase di sviluppo. Come fare per garantire la stessa esperienza su tutti i browser senza rinunciare alle performance? La risposta è il polyfill progressivo, una strategia a tre livelli che garantisce il miglior risultato possibile su ogni browser.
Il problema della compatibilità
La proprietà animation-timeline è supportata nativamente da:
- Chrome 115+ ✓
- Edge 115+ ✓
- Opera 101+ ✓
- Safari 18+ ✗ (supporto parziale/in sviluppo)
- Firefox ✗ (in sviluppo, abilitabile tramite flag)
- Samsung Internet ✗ (in sviluppo)
Secondo i dati di caniuse.com, a inizio 2026 circa il 65-70% degli utenti globali ha un browser con supporto nativo. Questo significa che circa il 30-35% degli utenti ha bisogno di un polyfill per vedere le animazioni scroll-driven.
La strategia del polyfill progressivo
La strategia migliore prevede 3 livelli di fallback. Ogni livello cerca di offrire la migliore esperienza possibile in base alle capacità del browser.
Livello 1: CSS nativo (browser moderni)
Scrivi le animazioni con animation-timeline: view() come standard primario. I browser che la supportano ottengono animazioni scroll-driven fluide con zero JavaScript.
.animato {
animation: fadeUp 1s ease both;
animation-timeline: view();
animation-range: entry 0% entry 100%;
}Livello 2: Fallback CSS (browser senza supporto né JS)
Per i browser che non supportano animation-timeline e hanno JavaScript disabilitato, la strategia è trasformare l”animazione scroll-driven in un”animazione temporale. Basta aggiungere animation-duration e configurare animation-iteration-count: 2 con animation-direction: alternate per simulare l”effetto di entrata-uscita:
.animato {
animation: fadeUp 1s ease both;
animation-timeline: view();
/* Fallback per browser non supportati: */
animation-duration: 1s;
animation-iteration-count: 2;
animation-direction: alternate;
}In questo modo, anche senza il supporto nativo e senza JavaScript, l”utente vede comunque un”animazione (anche se non legata allo scroll).
Livello 3: Polyfill JavaScript (browser senza supporto JS abilitato)
Il cuore del polyfill: un JavaScript leggero che rileva se il browser supporta animation-timeline, e se non lo supporta, attiva uno scroll observer che mappa la posizione dell”elemento all”avanzamento dell”animazione.
Il polyfill spiegato in dettaglio
(function() {
// 1. Feature detection: il browser supporta animation-timeline?
if (window.CSS && CSS.supports('animation-timeline', 'view()')) {
return; // Browser moderno, zero JS necessario
}
// 2. Il browser non supporta: attiva il polyfill
const elements = document.querySelectorAll('.animato');
// 3. Funzione di aggiornamento (chiamata ad ogni frame di scroll)
function update() {
const viewportHeight = window.innerHeight;
const scrollY = window.scrollY || window.pageYOffset;
elements.forEach(function(el) {
const rect = el.getBoundingClientRect();
const elTop = rect.top + scrollY;
const elHeight = rect.height;
// Calcola il progresso (da 0 a 1)
var progress = (scrollY + viewportHeight - elTop) / (elHeight + viewportHeight);
progress = Math.max(0, Math.min(1, progress));
// Browser non supportano animation-delay negativo su animation: paused
// quindi usiamo l''approccio alternativo: animation-delay
el.style.animationDelay = '-' + progress + 's';
el.style.animationPlayState = 'paused';
});
requestAnimationFrame(update);
}
// 4. Avvia il polyfill
update();
})();Ottimizzazioni del polyfill
Un buon polyfill non si limita a funzionare, ma deve anche essere efficiente. Le ottimizzazioni chiave sono:
MutationObserver per elementi dinamici
Se nuovi elementi vengono aggiunti al DOM dopo il caricamento (ad esempio, in una single-page application o in un carosello), il polyfill deve rilevarli:
const observer = new MutationObserver(function() {
// Rianalizza il DOM per nuovi elementi animati
elements = document.querySelectorAll('.animato');
});
observer.observe(document.body, { childList: true, subtree: true });Throttling con requestAnimationFrame
Usare requestAnimationFrame invece di ascoltare direttamente l”evento scroll garantisce che l”aggiornamento avvenga al massimo 60 volte al secondo, in sincronia con il refresh del monitor.
Rispetto di prefers-reduced-motion
Un polyfill accessibile deve rispettare le preferenze utente:
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
return; // Non attivare animazioni per utenti che preferiscono movimento ridotto
}Come testare il polyfill
Per verificare che il polyfill funzioni correttamente:
- Apri il sito in Chrome e verifica che le animazioni funzionino (CSS nativo)
- Apri il sito in Firefox e verifica che le animazioni funzionino (polyfill JS)
- Disabilita JavaScript in Firefox e verifica il fallback CSS (animazione temporale)
- Testa su Safari (sia desktop che mobile)
- Usa Chrome DevTools > Rendering > Emulate CSS media type > prefers-reduced-motion
ClassyBlocks Pro: polyfill automatico, zero configurazioni
ClassyBlocks Pro implementa questa strategia in modo trasparente. Il plugin:
- Rileva automaticamente il supporto del browser via
CSS.supports('animation-timeline', 'view()') - Su Chrome/Edge/Opera: animazioni CSS native, zero JS, 100 Lighthouse
- Su Safari/Firefox/Legacy: polyfill JS automatico, stessa esperienza utente
- CSS fallback per browser senza JavaScript
- Rispetta prefers-reduced-motion
- MutationObserver per elementi dinamici
151 animazioni in 12 pack, zero configurazioni, massime performance su ogni browser.



