Salta al contenuto principale

08 - 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. La variante same-document è Baseline 2025, mentre le cross-document transitions raggiungono piena interoperabilità nel 2026.

Cosa ne pensi di questo articolo?

08 - View Transitions API: Animazioni di Navigazione Native
Core Web VitalsFoto:Bibek ghoshPexels

In Breve

La View Transitions API porta le animazioni fluide delle app native direttamente nel browser, senza librerie di terze parti. La variante same-document è Baseline 2025, mentre le cross-document transitions raggiungono piena interoperabilità nel 2026.

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-transition e ::view-transition-old/new pseudo-elementi
  • Applicare view-transition-name per 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-transition e coordinamento lato server/browser.

Same-Document: Fondamenti con startViewTransition()

Per animare una transizione same-document, il flusso è semplice:

  1. Racchiudi l'update del DOM dentro document.startViewTransition(() => { ... })
  2. Il browser cattura uno snapshot dello stato attuale (old view)
  3. Il callback aggiorna il DOM (new view)
  4. Il browser crea un overlay pseudo-elemento ::view-transition
  5. 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.

Prova Questi Strumenti

Strumenti gratuiti correlati a questo argomento.

Commenti

Caricamento commenti...

Accedi per commentare

Discuti questo articolo nella community

Unisciti al gruppo Telegram per discutere con altri sviluppatori, fare domande e condividere le tue esperienze.

Ti è piaciuto questo articolo?

Esplora altri contenuti sul blog o scopri i miei progetti