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.

CasoCosa serveNota
Cambio pagina@view-transition { navigation: auto }solo fra pagine dello stesso origin
Elemento condivisoview-transition-name unicouno per pagina, non due
Applicazione SPAdocument.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-motion in 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.