Sviluppo web
View transitions senza SPA: cosa funziona fra due pagine HTML
Le view transitions cross-document animano il passaggio fra due pagine HTML con una regola CSS, senza SPA. Dove funzionano e dove la pagina resta istantanea.
In sintesi
- Una regola @view-transition { navigation: auto } accende la transizione fra pagine dello stesso sito.
- Gli elementi condivisi richiedono lo stesso view-transition-name nelle due pagine, unico per pagina.
- Dove l'API manca la navigazione resta istantanea: è un miglioramento, non una dipendenza.
Risposta breve: le view transitions cross-document animano il passaggio fra due pagine HTML con una regola CSS, senza SPA. Chrome 126+ e Safari 18.2+ le supportano; altrove la navigazione resta istantanea, senza errori.
Il minimo che funziona
@view-transition {
navigation: auto;
}
::view-transition-old(root) {
animation: 180ms ease-out both fade-out;
}
::view-transition-new(root) {
animation: 180ms ease-in both fade-in;
}
@media (prefers-reduced-motion: reduce) {
::view-transition-old(root),
::view-transition-new(root) { animation: none; }
}
Basta questo per un cross-fade su ogni navigazione fra pagine dello stesso origin. Le due animazioni fade-out e fade-in vanno definite con @keyframes nel tuo foglio: il browser non le fornisce.
Elementi condivisi
.card__media { view-transition-name: cover; }
.card__title { view-transition-name: title; }
/* la stessa coppia di nomi nella pagina di destinazione */
.article__media { view-transition-name: cover; }
.article__title { view-transition-name: title; }
Il nome deve essere unico nella pagina. Se due elementi lo condividono il browser annulla la transizione di quell'elemento: è l'errore che si vede più spesso, e non produce nessun messaggio in console.
| Caso | Cosa serve | Nota |
|---|---|---|
| Cambio pagina | @view-transition { navigation: auto } | solo fra pagine dello stesso origin |
| Elemento condiviso | view-transition-name unico | uno per pagina, non due |
| Applicazione SPA | document.startViewTransition() | richiede un callback che aggiorna il DOM |
Il cross-document non richiede JavaScript: la transizione parte anche con il tasto indietro e con un link aperto in una nuova scheda. Il supporto però non è universale, quindi la regola va trattata come miglioramento progressivo.
Il limite
Tre limiti reali. Primo: la transizione non sopravvive a un cambio di tema fra le due pagine, perché il cross-fade mostra due layout diversi. Secondo: Firefox non le supporta ancora, e va verificato su caniuse il giorno in cui pubblichi. Terzo: il browser fa un'istantanea della pagina, quindi su documenti enormi il costo si sente sul frame.
Come verificarlo
- Emula
prefers-reduced-motionin DevTools: non deve restare nessuna animazione. - Naviga con la tastiera: la transizione non deve mangiarsi il focus né l'ordine di tabulazione.
- Cerca un nome duplicato: con due uguali la transizione sparisce in silenzio.
- Prova il tasto indietro: la transizione deve partire anche lì, non solo sui link.
Dove continuare
Nel catalogo: blocco blog, componenti e blocchi. Le guide: view transitions in Astro e animazioni CSS in Tailwind; il confronto: Tailwind contro CSS Modules.
Domande frequenti
Serve una SPA per usarle?
No. Il caso cross-document anima la navigazione fra due documenti veri. La SPA serve solo se vuoi controllare il momento dell'aggiornamento del DOM.
Funzionano su Safari e Firefox?
Safari le supporta dalla 18.2, Chrome dalla 126. Firefox è ancora indietro: senza supporto la navigazione resta istantanea, senza rompere nulla.
Perché la transizione non parte?
Quasi sempre per un nome duplicato o perché la regola <code>@view-transition</code> manca in una delle due pagine. Servono entrambe.
Come le disattivo per chi preferisce meno movimento?
Con la media query <code>prefers-reduced-motion: reduce</code> che azzera le animazioni degli pseudo-elementi. Il browser rispetta la preferenza di sistema.
Pesano sui Core Web Vitals?
Il costo è un'istantanea per navigazione. Su pagine normali resta sotto il frame; su documenti molto lunghi conviene misurare l'INP con il pannello Performance.