View Transitions API per MPA: Transizioni Fluide tra Pagine Multi-Documento nel 2026
Guida pratica alla View Transitions API cross-document per siti multi-pagina nel 2026: come attivarla con una regola CSS, personalizzarla con pageswap/pagereveal e combinarla con Speculation Rules senza impattare Core Web Vitals.
La View Transitions API per MPA è un'API web nativa che consente di animare in modo fluido il passaggio tra due pagine HTML distinte di un sito multi-documento, sfruttando la regola CSS @view-transition e gli eventi pageswap/pagereveal, senza dipendere da framework JavaScript o architetture SPA. Nel 2026, con il supporto Baseline nei browser Chromium (Chrome, Edge, Opera) dalla versione 126 e l'implementazione in corso in Firefox e Safari, questa tecnologia elimina il tradizionale "flash bianco" tra navigazioni e migliora la percezione della velocità senza penalizzare i Core Web Vitals.
Le view transitions cross-document funzionano su siti multi-pagina tradizionali (MPA) senza richiedere una Single Page Application.
L'attivazione richiede una singola regola CSS: @view-transition { navigation: auto; } su entrambe le pagine coinvolte, purché same-origin.
Chrome 126+ (giugno 2024) offre supporto stabile; nel 2026 la copertura Chromium supera l'85% del traffico globale.
Gli eventi pageswap e pagereveal permettono di personalizzare snapshot e animazioni al volo, anche con dati asincroni.
Combinate con la Speculation Rules API, riducono il tempo percepito di navigazione a zero millisecondi.
Non influiscono negativamente su LCP, CLS o INP se implementate correttamente; il rendering avviene su un livello compositor separato.
Cos'è la View Transitions API?
La View Transitions API è uno standard web che permette al browser di catturare snapshot dello stato "prima" e "dopo" di una navigazione o di un aggiornamento del DOM, per poi interpolare visivamente i due stati con animazioni CSS. Introdotta inizialmente per applicazioni single-page (SPA) in Chrome 111 (marzo 2023), l'API è stata estesa nel giugno 2024 alle navigazioni multi-documento con Chrome 126, portando le stesse capacità a qualsiasi sito HTML tradizionale.
Il meccanismo alla base è concettualmente semplice. Quando il browser rileva una transizione idonea, scatta una "fotografia" della pagina uscente, avvia il caricamento della pagina entrante, ne scatta una seconda al primo paint utile e infine anima gli elementi corrispondenti su un livello compositor dedicato. Questo evita il tipico "flash of white" (FOUC di navigazione) e produce transizioni fluide, simili a quelle delle app native, senza richiedere un layer JavaScript pesante.
Nel contesto delle prestazioni web, la View Transitions API non riduce il tempo effettivo di caricamento. Migliora però la percezione di velocità, una metrica che studi Google hanno dimostrato correlata al tasso di conversione più fortemente di alcune metriche tecniche pure. È uno strumento di UX performativa, non di ottimizzazione della rete. La prima volta che l'ho attivata su un blog Astro con una singola riga di CSS, ho pensato onestamente ci fosse un bug: sembrava troppo semplice per funzionare così bene.
Same-document vs cross-document: qual è la differenza?
Prima di scrivere codice è fondamentale distinguere le due varianti dell'API, perché richiedono attivazioni diverse e coprono casi d'uso opposti.
Caratteristica
Same-document (SPA)
Cross-document (MPA)
API di attivazione
document.startViewTransition()
CSS @view-transition
Tipo di navigazione
Aggiornamento DOM in-place
Navigazione HTTP tra due documenti
Vincoli
Stesso documento
Solo same-origin
Disponibile da
Chrome 111 (marzo 2023)
Chrome 126 (giugno 2024)
JavaScript richiesto
Sì, per orchestrare
No, funziona anche in HTML statico
Eventi correlati
ViewTransition promise
pageswap, pagereveal
Casi d'uso tipici
React, Vue, router client
Blog, e-commerce classici, siti statici
La variante cross-document è quella rilevante per la maggior parte dei siti "tradizionali" (WordPress, Shopify, Astro in modalità MPA, siti Jamstack pre-renderizzati) perché non richiede di trasformare l'architettura in un'app JavaScript per ottenere transizioni fluide. È anche la scelta corretta per progetti che privilegiano la velocità di TTFB e il Server-Side Rendering rispetto al peso dei bundle client.
Come abilitare le view transitions cross-document
L'attivazione base richiede una sola regola CSS, presente in entrambe le pagine coinvolte nella navigazione. Se manca su una delle due, il browser fa il fallback silenzioso alla navigazione tradizionale.
/* styles.css — incluso su ogni pagina del sito */
@view-transition {
navigation: auto;
}
Il valore auto indica al browser di attivare la transizione per tutte le navigazioni same-origin idonee: click su link, submit di form GET, e chiamate a history.back()/forward(). Le navigazioni cross-origin, i reload e i redirect esterni sono esclusi per motivi di sicurezza (impedirebbero altrimenti di misurare il tempo di caricamento di siti terzi).
L'animazione predefinita è un cross-fade di 250 millisecondi. Per personalizzarla, si agisce sugli pseudo-elementi generati automaticamente dal browser:
/* Slide orizzontale al posto del cross-fade */
::view-transition-old(root) {
animation: 300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-out;
}
::view-transition-new(root) {
animation: 300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-in;
}
@keyframes slide-out {
to { transform: translateX(-30%); opacity: 0; }
}
@keyframes slide-in {
from { transform: translateX(30%); opacity: 0; }
}
Lo pseudo-elemento ::view-transition-old(root) rappresenta lo snapshot della pagina uscente, mentre ::view-transition-new(root) è quello della pagina entrante. L'argomento root indica che stiamo animando l'intera viewport come un blocco unico; nella prossima sezione vedremo come segmentare in più elementi indipendenti.
Animazioni personalizzate con view-transition-name
Per ottenere transizioni "morphing", dove un elemento specifico si sposta o si trasforma tra due pagine, occorre assegnargli un nome univoco tramite la proprietà CSS view-transition-name. Se lo stesso nome esiste su entrambe le pagine, il browser tratta i due elementi come corrispondenti e li anima come un unico oggetto continuo.
/* Pagina di listing prodotti */
.product-card img[data-id="42"] {
view-transition-name: product-hero-42;
}
/* Pagina di dettaglio del prodotto 42 */
.product-detail-hero img {
view-transition-name: product-hero-42;
}
/* Animazione condivisa */
::view-transition-group(product-hero-42) {
animation-duration: 400ms;
animation-timing-function: cubic-bezier(0.32, 0.72, 0, 1);
}
Il risultato è che l'immagine del prodotto sembra "volare" dalla card di listing alla posizione hero della pagina di dettaglio, ridimensionandosi e riposizionandosi in modo continuo. Questo pattern è particolarmente efficace in e-commerce, gallerie fotografiche e liste di articoli, contesti dove l'utente conserva un forte "riferimento visivo" tra le due pagine.
Eventi pageswap e pagereveal per il controllo fine
Per casi d'uso avanzati, come assegnare nomi dinamicamente, ritardare la transizione in attesa di dati, o cambiare stile in base all'URL di destinazione, sono disponibili due eventi lato JavaScript: pageswap sulla pagina uscente e pagereveal sulla pagina entrante.
// Sulla pagina uscente: assegna view-transition-name in base
// all'URL di destinazione prima dello snapshot
window.addEventListener('pageswap', async (event) => {
if (!event.viewTransition) return;
const toUrl = new URL(event.activation.entry.url);
const productId = toUrl.pathname.match(/\/product\/(\d+)/)?.[1];
if (productId) {
const card = document.querySelector(`[data-product-id="${productId}"] img`);
if (card) card.style.viewTransitionName = 'product-hero';
}
});
// Sulla pagina entrante: rimuovi il nome dopo l'animazione
// per evitare che persista in navigazioni successive
window.addEventListener('pagereveal', async (event) => {
if (!event.viewTransition) return;
const hero = document.querySelector('.product-detail-hero img');
if (hero) hero.style.viewTransitionName = 'product-hero';
await event.viewTransition.finished;
if (hero) hero.style.viewTransitionName = '';
});
La proprietà event.viewTransition è un oggetto ViewTransition con le promise ready, updateCallbackDone e finished, utili per orchestrare animazioni sequenziali o annullare la transizione in caso di errore. Se l'evento arriva ma viewTransition è null, significa che la transizione non si è attivata (per esempio, il CSS @view-transition manca sulla pagina di destinazione).
View Transitions + Speculation Rules per navigazioni istantanee
La combinazione più potente per la performance percepita nel 2026 è l'accoppiamento di view transitions cross-document con la Speculation Rules API. Il browser preleva e pre-renderizza in background la pagina di destinazione più probabile; quando l'utente clicca, la transizione anima da uno snapshot già disponibile a un documento già renderizzato, portando il tempo effettivo di navigazione sotto i 50 ms.
In questa configurazione, il browser prerenderizza le pagine prodotto al passaggio del puntatore o al touchstart (eagerness "moderate"), e la view transition anima da/verso stati già pronti. Il risultato per l'utente è indistinguibile da un'app nativa. Il costo? Un piccolo aumento di traffico verso il server per le pagine effettivamente prerenderizzate, mitigabile con eagerness più conservativa in mobile o su connessioni save-data. Onestamente, questa è la parte in cui la maggior parte dei team esagera: iniziare con "moderate" su un percorso caldo, poi allargare.
Supporto browser e fallback nel 2026
Il panorama di supporto a settembre 2026 è il seguente:
Chromium (Chrome, Edge, Opera, Brave, Samsung Internet): stabile da Chrome 126 (giugno 2024). Copre circa l'85% del traffico globale desktop e mobile.
Firefox: implementazione in corso dietro il flag dom.viewTransitions.enabled; abilitazione predefinita prevista nel corso del 2026.
Safari: supporto same-document da Safari 18 (settembre 2024); il cross-document è in Technology Preview e non ancora in release stabile.
Il fallback è automatico e sicuro: browser senza supporto ignorano la regola @view-transition e gli eventi pageswap/pagereveal, eseguendo navigazioni tradizionali senza errori. Non serve @supports né polyfill. Per attivare stili solo dove la feature è disponibile, si può comunque usare:
Una preoccupazione legittima è se le view transitions penalizzino le metriche misurate da Chrome UX Report e usate da Google per il ranking. La risposta breve? No, se implementate correttamente. Analizziamo metrica per metrica.
LCP (Largest Contentful Paint)
LCP misura il momento in cui viene renderizzato l'elemento più grande visibile nel viewport iniziale. Le view transitions non ritardano questo momento perché il browser esegue lo snapshot dopo il primo paint utile della nuova pagina: LCP viene registrato normalmente, prima che l'animazione inizi. Anzi, la combinazione con fetchpriority e preload per LCP resta pienamente compatibile.
CLS (Cumulative Layout Shift)
Le animazioni delle view transitions avvengono su un livello compositor separato e sono considerate transizioni intenzionali dell'utente, quindi non contano come layout shift ai fini di CLS. Anche animazioni aggressive di trasformazione non generano penalità.
INP (Interaction to Next Paint)
Il rischio principale è che script eseguiti in pageswap o pagereveal blocchino il main thread. Se il gestore pageswap esegue lavoro sincrono pesante, l'interazione (il click) verrà misurata come lenta. La soluzione è mantenere gli handler snelli e delegare a requestIdleCallback tutto ciò che non è strettamente necessario per configurare la transizione. Vedi la nostra guida su ottimizzazione INP per pattern applicabili anche qui.
Errori comuni e come risolverli
La transizione non parte affatto
Cause frequenti in ordine di probabilità: la regola @view-transition manca sulla pagina di destinazione; le due pagine sono cross-origin (anche sottodomini diversi lo sono, per l'API); il click è avvenuto con Ctrl/Cmd (apre in nuova tab e la transizione viene saltata); si sta usando un router client-side che intercetta il click e chiama preventDefault().
Elementi che appaiono duplicati durante l'animazione
Il rendering dello snapshot ::view-transition-old e la pagina "vera" possono sovrapporsi se lo stile z-index è invertito. Assicurati che nulla nel DOM live abbia uno z-index superiore agli pseudo-elementi delle transizioni (che di default sono nel top layer).
Flicker su elementi fixed
Header, sidebar e footer position: fixed vanno esclusi dallo snapshot root con view-transition-name: none se non si vuole vederli scivolare via insieme al contenuto principale.
Test in produzione
Per verificare che le transizioni funzionino sotto carico reale, usa un tool RUM (Real User Monitoring) e traccia l'evento pageswap come custom mark. Web Vitals JS di Google, descritto nel documento ufficiale web.dev sui Core Web Vitals, può essere esteso con marker personalizzati per correlare navigazioni animate e metriche di UX.
Domande frequenti
La View Transitions API funziona con navigazioni cross-origin?
No. Per motivi di sicurezza e privacy, le view transitions cross-document si attivano solo tra pagine dello stesso origin (stesso schema, host e porta). Anche sottodomini diversi (es. www.esempio.it verso blog.esempio.it) sono considerati cross-origin e non attivano la transizione.
Devo usare un framework per implementare le view transitions su un sito multi-pagina?
No. La forza della variante cross-document è che funziona con HTML puro, senza JavaScript e senza framework. Basta aggiungere @view-transition { navigation: auto; } al CSS di entrambe le pagine. Framework come Astro, Nuxt e SvelteKit offrono astrazioni comode ma non sono necessarie.
Safari supporta le view transitions cross-document nel 2026?
Safari supporta la variante same-document dalla versione 18 (settembre 2024). La variante cross-document è in Safari Technology Preview e attesa in una release stabile durante il 2026. Fino ad allora, Safari fa fallback automatico a navigazioni tradizionali senza errori.
Le view transitions peggiorano l'INP o il CLS?
No, se gli handler pageswap/pagereveal restano leggeri. Le animazioni avvengono su compositor separato quindi non generano CLS, e non influiscono su INP purché il codice JavaScript associato non blocchi il main thread per più di 50 ms.
Qual è la differenza tra View Transitions e Speculation Rules?
Speculation Rules pre-carica o pre-renderizza la pagina di destinazione prima che l'utente clicchi, riducendo il tempo tecnico di navigazione. View Transitions anima il passaggio visivo tra le due pagine. Sono complementari: usate insieme, offrono navigazioni percepite come istantanee.
Posso disabilitare le view transitions su utenti con prefers-reduced-motion?
Sì, ed è una buona pratica di accessibilità. Avvolgi le regole di animazione personalizzate in @media (prefers-reduced-motion: no-preference), oppure imposta animation-duration: 0.001s su ::view-transition-group(*) quando l'utente preferisce meno movimento.
Come costruire un RUM custom con PerformanceObserver per misurare LCP, INP e CLS sugli utenti reali: codice pratico, sendBeacon e attribuzione con LoAF.
content-visibility: auto e la proprieta CSS che salta il rendering degli elementi fuori viewport. Guida 2026 con esempi pratici, supporto browser aggiornato e trappole comuni da evitare.
Configura stale-while-revalidate e stale-if-error per servire contenuti istantanei con TTFB vicino allo zero. Include esempi Cloudflare, Fastly, Vercel e Next.js 15.