View Transitions API: Animazioni di Navigazione Native
La View Transitions API porta le animazioni fluide delle app native direttamente nel browser, senza librerie di terze parti. Una volta attivata, il passaggio tra le view di una SPA o tra le pagine di un sito tradizionale produce automaticamente una transizione visiva fluida. La variante same-document è Baseline 2025 (supporto universale), mentre le cross-document transitions raggiungono piena interoperabilità nel 2026. Con questa API, il tuo sito esce dall'ordinario.
Fino ad oggi, le animazioni di navigazione richiedevano librerie esterne come Framer Motion o GSAP, oppure JavaScript manuale con timing e sincronizzazione delicata. La View Transitions API elimina questa complessità: il browser gestisce automaticamente lo snapshot dello stato precedente, crea un pseudo-elemento overlay, e anima la transizione con le regole CSS che tu definisci. Nessuna libreria, nessun JavaScript laborioso, nessun rischio di flicker.
Cosa Imparerai
- Differenza tra same-document e cross-document view transitions
- Come usare
document.startViewTransition()nelle SPA - CSS
::view-transitione::view-transition-old/newpseudo-elementi - Applicare
view-transition-nameper controllare animazioni granulari - Integrare view transitions in Angular, React, Vue e framework moderni
- Fallback e progressive enhancement per browser legacy
- Accessibilità con
prefers-reduced-motion - Performance tips e problemi comuni
Same-Document vs Cross-Document View Transitions
La View Transitions API supporta due scenari diversi, ognuno con implicazioni architetturali diverse:
- Same-document transitions: Cambio di view all'interno della stessa pagina (SPA). Esempio: navigazione tra tab, cambio di route in Angular/React. Baseline 2025, supporto universale.
-
Cross-document transitions: Navigazione da una pagina HTML completamente
diversa a un'altra (MPA tradizionale). Esempio: link da /article/1 a /article/2. Raggiunge
Baseline nel 2026, ma Chrome e Edge supportano già da v111 (2023). Richiede attribute HTML
@view-transitione coordinamento lato server/browser.
Same-Document: Fondamenti con startViewTransition()
Per animare una transizione same-document, il flusso è semplice:
- Racchiudi l'update del DOM dentro
document.startViewTransition(() => { ... }) - Il browser cattura uno snapshot dello stato attuale (old view)
- Il callback aggiorna il DOM (new view)
- Il browser crea un overlay pseudo-elemento
::view-transition - Anima la transizione con CSS rules
// Esempio: cambio di route in una SPA (Angular)
// Nel tuo service di navigazione o componente
async navigateToArticle(id: number) {
// Controlla se l'API è disponibile
if ('startViewTransition' in document) {
// Wrappa l'update del DOM
await (document as any).startViewTransition(async () => {
// Aggiorna il DOM: stato reattivo, store, router, etc.
this.currentArticleId = id;
this.article$ = this.backend.getArticle(id);
// La transizione animerà il cambio automaticamente
});
} else {
// Fallback: aggiorna senza transizione su browser legacy
this.currentArticleId = id;
this.article$ = this.backend.getArticle(id);
}
}
Pseudo-Elementi ::view-transition
Una volta che startViewTransition() è attivo, il browser crea automaticamente
una struttura pseudo-elemento:
/* La struttura pseudo creata dal browser (logica, non nel DOM reale) */
::view-transition
::view-transition-group(root)
::view-transition-image-pair(root)
::view-transition-old(root) /* Screenshot dello stato precedente */
::view-transition-new(root) /* Nuova view */
Puoi targetizzare questi pseudo-elementi con CSS per controllare l'animazione esattamente come desideri:
/* Animazione di fade predefinita (browser default) */
::view-transition {
/* Personalizza il comportamento della transizione */
}
/* Anima solo la vecchia view */
::view-transition-old(root) {
animation: slide-out-left 0.6s cubic-bezier(0.4, 0, 1, 1);
}
/* Anima solo la nuova view */
::view-transition-new(root) {
animation: slide-in-right 0.6s cubic-bezier(0, 0, 0.2, 1);
}
@keyframes slide-out-left {
from {
opacity: 1;
transform: translateX(0);
}
to {
opacity: 0;
transform: translateX(-100%);
}
}
@keyframes slide-in-right {
from {
opacity: 0;
transform: translateX(100%);
}
to {
opacity: 1;
transform: translateX(0);
}
}
view-transition-name: Animazioni Granulari per Elemento
Per impostazione predefinita, l'intera pagina viene animata come un'unica unità. Se vuoi che
elementi diversi si animino in modo indipendente (es: header rimane al suo posto mentre il
contenuto scorre), usa view-transition-name:
/* HTML */
<header class="sticky-header">Titolo</header>
<main class="article-content">...contenuto...</main>
/* CSS */
.sticky-header {
view-transition-name: header;
}
.article-content {
view-transition-name: content;
}
/* Anima solo il contenuto, il header rimane statico */
::view-transition-old(content) {
animation: fade-out 0.3s ease-out;
}
::view-transition-new(content) {
animation: fade-in 0.3s ease-out;
}
@keyframes fade-out {
from { opacity: 1; }
to { opacity: 0; }
}
@keyframes fade-in {
from { opacity: 0; }
to { opacity: 1; }
}
Questo permette pattern complessi come:
- Header/footer fissi, solo il main content anima
- Immagini hero che zoomano mentre il testo dissolvenza
- Sidebar che scorre in mentre il main content si sposta
Integrazione in SPA: Angular, React, Vue
Angular (con rxjs e router events)
// service: view-transition.service.ts
import { Injectable } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';
import { filter } from 'rxjs';
@Injectable({ providedIn: 'root' })
export class ViewTransitionService {
constructor(private router: Router) {
this.init();
}
private init() {
this.router.events
.pipe(filter(event => event instanceof NavigationEnd))
.subscribe(async () => {
if ('startViewTransition' in document) {
await (document as any).startViewTransition(() => {
// Angular ha già aggiornato il template
});
}
});
}
}
React (con useEffect e router)
// useViewTransition.ts
import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
export function useViewTransition() {
const location = useLocation();
useEffect(() => {
if ('startViewTransition' in document) {
(document as any).startViewTransition(() => {
// React ha già re-renderizzato
});
}
}, [location.pathname]);
}
// Uso nel componente
function ArticlePage() {
useViewTransition();
return {...} ;
}
Cross-Document Transitions: Navigazione MPA
Per i siti tradizionali con navigazione da pagina a pagina, il browser coordina la transizione automaticamente senza JavaScript, ma richiede che il server comunichi il supporto tramite HTTP header:
/* Nel server (Nginx, Express, etc.) */
/* Aggiungi l'header HTTP */
Link: </styles.css>; rel="preload"; as="style"
/* Nel CSS della pagina, assegna nomi alle regioni */
.header {
view-transition-name: page-header;
}
.article {
view-transition-name: page-article;
}
/* Animazioni per cross-document */
::view-transition-old(page-article) {
animation: slide-fade-out 0.4s ease;
}
::view-transition-new(page-article) {
animation: slide-fade-in 0.4s ease;
}
SSR (Server-Side Rendering) e Considerazioni
La View Transitions API è client-side e completamente compatibile con SSR:
- SSR rendering: Il server renderizza l'HTML iniziale, nessun problema con View Transitions.
- Client hydration: Dopo che Angular/React completa l'hydration, la navigazione client-side può attivare transizioni.
- First load: La prima pagina non viene animata (no "old" view). Le transizioni iniziano dalla seconda navigazione.
// Negli strumenti di SSR/hydration di Angular (server.ts)
// o nell'entry point di React, nessuna configurazione speciale è necessaria.
// La View Transitions API è completamente trasparente all'SSR.
// Tuttavia, ti conviene comunque wrappare la logica di navigazione:
async handleNavigation(route: string) {
if ('startViewTransition' in document) {
await (document as any).startViewTransition(async () => {
await this.router.navigate([route]);
});
} else {
await this.router.navigate([route]);
}
}
Progressive Enhancement e Fallback
L'API è relativamente nuova: Firefox e Safari stanno ancora aggiungendo supporto completo. Le strategie di fallback sono semplici:
// Controlla il supporto prima di usare
if (document.startViewTransition) {
// Usa la View Transitions API
await document.startViewTransition(updateDOM);
} else {
// Fallback: aggiorna il DOM senza transizione
updateDOM();
}
// Oppure usando feature detection nel CSS
@supports (view-transition-name: auto) {
/* Regole CSS che sfruttano View Transitions */
::view-transition-old(root) {
animation: slide-out 0.6s ease;
}
}
/* Se non supportata, nessuna animazione */
Accessibilità: prefers-reduced-motion
Non tutte le persone vogliono animazioni. Rispetta sempre la preferenza dell'utente tramite
la media query prefers-reduced-motion:
/* Disabilita animazioni per utenti sensibili al movimento */
@media (prefers-reduced-motion: reduce) {
::view-transition-old(root),
::view-transition-new(root) {
animation: none !important;
opacity: 1 !important;
}
}
// Oppure nel JavaScript, salta completamente la transizione:
async handleNavigation(route: string) {
const prefersReduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
if ('startViewTransition' in document && !prefersReduced) {
await (document as any).startViewTransition(updateDOM);
} else {
updateDOM();
}
}
Performance Tips e Problemi Comuni
Sebbene la View Transitions API sia generalmente efficiente, ci sono ottimizzazioni da considerare:
- Snapshot cost: Catturare lo snapshot della pagina ha un costo. Su pagine molto grandi (100MB+ di DOM), lo snapshot può durare millisecondi. Per siti normali, è trascurabile.
- Animation duration: Mantieni animazioni brevi (300-600ms). Animazioni lunghe possono sembrare rallentamenti.
- Compositing layers: La transizione crea un compositing layer. Evita di animare elementi will-change pesanti durante la transizione.
- Debug flicker: Se il contenuto "lampeggia", controlla che l'aggiornamento del DOM sia dentro il callback di startViewTransition().
Casi d'Uso Reali
La View Transitions API brilla in scenari come:
- Blog/News site: Transitare tra articoli con transizione smooth automatica.
- E-commerce: Navigare tra categorie di prodotti con animazione fluida.
- Admin dashboard: Tab e pagine che si animano professionalmente.
- SPA framework: Qualsiasi app Angular/React/Vue che cambia rotta beneficia automaticamente.
FAQ: Domande Frequenti
Quali browser supportano View Transitions?
Same-document (Baseline 2025): Chrome 111+, Edge 111+, Opera 97+, Firefox 119+. Safari supporto arriva a breve. Cross-document: Chrome 111+ e Edge 111+ oggi; supporto universale nel 2026.
Posso usare View Transitions con Next.js, Nuxt o altri framework?
Sì. Qualsiasi framework che supporta navigazione client-side (router) può usare
startViewTransition(). Alcuni framework stanno aggiungendo helper built-in (Next.js 13+).
Peggiorerà le performance del mio sito?
No. Lo snapshot e l'animazione hanno costo trascurabile su pagine normali. Su pagine enormi (10MB+ di DOM) il costo di snapshot è di pochi millisecondi. L'API è ottimizzata dal browser.
Posso controllare la durata e la timing della transizione?
Completamente. Usa i normali CSS properties animation-duration,
animation-timing-function, etc. sugli pseudo-elementi.
Funziona con iFrame?
No. Le transizioni sono scoped alla finestra principale del documento. iFrame non possono avviare transizioni della pagina parent. Per cross-frame communication, usa PostMessage.
Conclusioni
La View Transitions API rappresenta un cambio di paradigma nelle animazioni web. Per la prima volta, il browser stesso gestisce il coordinamento tra snapshot, overlays e timing, liberando gli sviluppatori da JavaScript laborioso e timing delicato. Con supporto Baseline 2025 per same-document e completo nel 2026 per cross-document, questa API diventerà lo standard de facto per le navigazioni fluide nei prossimi anni.
La strategia consigliata: inizia ad usare startViewTransition() nelle tue SPA oggi
stesso (fallback elegante per browser legacy), e prepara le cross-document transitions per le
applicazioni MPA tradizionali nel 2026. Il tuo sito avrà l'aspetto di un'app nativa, senza una
sola libreria esterna.

Commenti
Caricamento commenti...
Accedi per commentare