6 ottobre 2026

View Transitions nel 2026: tipi, match-element, gruppi annidati e transizioni “scoped”

Le View Transitions stanno diventando abbastanza mature da gestire UI complesse senza hack: ecco cosa è cambiato e come sfruttarlo nel CSS di tutti i giorni.

Panoramica aggiornata sulle View Transitions: supporto browser, nuovi “types” per organizzare le animazioni, view-transition-name: match-element per evitare ID manuali, nested view transition groups (Chrome 140) per rispettare gerarchie e clipping, e scoped view transitions (Canary) per animare solo un sottoalbero lasciando il resto della pagina interattivo. Chiude con una nota sul futuro document.activeViewTransition.

Le View Transitions stanno rapidamente passando da “feature interessante” a strumento pratico per costruire interfacce più fluide: passaggi tra pagine meno bruschi, micro-interazioni che mantengono il contesto, morphing tra stati senza perdere la “posizione mentale” dell’utente.

Negli ultimi mesi sono arrivate diverse novità che rendono la tecnologia più gestibile in progetti reali: miglioramenti nel supporto cross-browser, nuove primitive per scalare in team e nuove opzioni per risolvere problemi storici come clipping, gerarchie e z-index.

Supporto browser: finalmente ci siamo (quasi)

Oggi:

  • Chrome supporta View Transitions sia same-document (SPA / interazioni nella stessa pagina) sia cross-document (navigazioni tra documenti).
  • Safari supporta entrambe (same-document e cross-document).
  • Firefox sta muovendo passi concreti: in Nightly risultano abilitate le same-document view transitions. È un segnale importante per l’obiettivo di interoperabilità.

Same-document vs cross-document, in breve

  • Same-document: avvii la transizione via JavaScript (tipico in SPA o in UI dinamiche: liste, tab, pannelli, ecc.).
  • Cross-document: la transizione scatta durante una navigazione tra pagine (MPA).

Questa distinzione conta perché alcune novità funzionano solo in uno dei due mondi.

View Transition “types”: la svolta per progetti grandi

Una delle aggiunte più utili è il concetto di tipi di transizione (view transition types): puoi etichettare una view transition con uno o più “types” e scrivere CSS che si attiva solo quando è in corso quel tipo specifico.

È esattamente ciò che serve quando:

  • hai più percorsi di navigazione con animazioni diverse (es. paginazione vs cambio sezione),
  • lavori in un team e vuoi evitare che regole CSS per transizioni diverse si pestino i piedi,
  • vuoi creare una libreria interna di transizioni riutilizzabili.

Esempio di scenario

Su un blog, passando da una pagina di elenco alla successiva potresti voler “fotografare” e animare:

  • titolo post,
  • pulsanti di paginazione,
  • elementi ripetuti (avatar autore, card, ecc.).

Ma andando dall’elenco alla pagina “About” magari vuoi una transizione più ampia che coinvolga:

  • header,
  • contenuto principale,
  • layout generale.

I types ti permettono di separare questi due casi in modo dichiarativo.

Come si impostano

  • Same-document: document.startViewTransition() accetta anche un oggetto con callback e types (array).
  • Cross-document: puoi aggiungere un descrittore types nella regola @view-transition.

Come si consumano in CSS

Arriva un selettore fondamentale:

:root:active-view-transition-type(my-type) {
  /* regole attive per tutta la durata della transizione */
}

Questo selettore è interessante perché vale per tutta la finestra temporale della transizione: da prima dello snapshot “old” fino alla fine. Risultato: puoi impostare view-transition-name e altre regole solo quando serve.

In aggiunta, esiste anche :active-view-transition, una pseudo-classe che matcha un elemento quando una view transition è stata avviata su di esso (utile per styling mirato durante l’animazione).

Nota sullo stato in Firefox: al momento è rilevante sapere che l’implementazione include view-transition-class, ma non necessariamente i types.

view-transition-name: match-element: addio gestione manuale degli ID

Un punto dolente tipico: per animare elementi ripetuti (card, righe di tabella, chip, ecc.) spesso serve assegnare un view-transition-name univoco per elemento.

Farne la gestione in JavaScript è noioso e fragile.

La novità è un valore speciale:

.card {
  view-transition-name: match-element;
}

Con match-element il browser genera automaticamente un nome univoco basato sull’identità interna del nodo DOM.

Limiti importanti

  • Non è utilizzabile in cross-document: su documenti diversi non esiste un’identità condivisa.
  • In same-document può diventare fragile se il tuo framework ricrea i nodi (es. re-render che sostituisce elementi invece di aggiornarli). Due elementi “uguali” visivamente possono essere due nodi diversi → identità diversa → match non garantito.

Soluzione per DOM ricreato: usare attr() come chiave stabile

Se hai un attributo stabile (es. id, data-id), puoi usare attr() in modo avanzato per derivare il nome dal dato, con fallback:

.card {
  view-transition-name: attr(data-id type(<custom-ident>), match-element);
}

Così:

  • prima prova a usare data-id come identificatore coerente,
  • se manca o non è valido, ripiega su match-element.

È un compromesso eccellente quando vuoi transizioni affidabili in UI dinamiche.

Nested View Transition Groups (Chrome 140): gerarchie, clipping e trasformazioni 3D

Con UI più sofisticate emerge un problema strutturale: quando elementi interni e contenitore devono animarsi insieme (e correttamente), la “pseudo-tree” delle view transitions può non rispettare la gerarchia reale.

Nested view transition groups risolvono questo punto:

  • permettono di annidare uno o più ::view-transition-group() dentro un altro,
  • migliorano il comportamento di opacity, mask, filter, transform, incluse combinazioni e scenari 3D,
  • aiutano a eliminare clipping anomalo e compositing inattesi.

Caso tipico

Una card con avatar:

  • la card si sposta (sidebar → colonna principale),
  • gli avatar all’interno cambiano dimensione.

Vogliamo che gli avatar si muovano “con” la card, come contenuto della card. Prima era difficile perché i gruppi risultavano fratelli invece che figli.

Nuova proprietà: view-transition-group

Si usa insieme a view-transition-name.

Approccio 1 (sul parent):

  • sul contenitore imposti view-transition-group: contain per contenere gli snapshot dei figli.

Approccio 2 (sui figli):

  • su ogni figlio imposti view-transition-group: nearest per agganciarsi al genitore più vicino con view-transition-name.

Internamente i figli finiscono raggruppati in un nuovo pseudo-elemento di appoggio: ::view-transition-group-content().

Clipping: dove applicarlo

Se vuoi clip del contenuto durante la transizione, la regola pratica è applicare:

::view-transition-group-content(card) {
  overflow: clip;
}

Questo è spesso “il pezzo mancante” quando si sperimentano gruppi annidati.

Scoped View Transitions (sperimentale): transizioni su un sottoalbero, pagina ancora interattiva

Se il tuo obiettivo principale è limitare l’effetto della view transition a una porzione di UI (un widget, una sidebar, un pannello), i nested group potrebbero essere più di quanto ti serve.

Qui entra in gioco una novità sperimentale (attualmente in Chrome Canary con flag): le scoped view transitions.

Invece di:

document.startViewTransition(() => {
  // update UI
});

puoi fare:

someElement.startViewTransition(() => {
  // update UI solo in quel sottoalbero
});

Perché è enorme

  • L’overlay della transizione viene iniettato dentro quell’elemento, non a livello documento.
  • Il resto della pagina rimane interattivo durante l’animazione.
  • Puoi avere più view transitions in parallelo se avvengono in sottoalberi diversi.

Effetto collaterale positivo: meno problemi di z-index e top layer

Un problema noto delle view transitions “globali” è che i pseudo-elementi possono essere disegnati sopra praticamente tutto, incluso contenuti in top layer (popover, dialog, ecc.). In passato si finiva con workaround discutibili: dare un view-transition-name anche a cose che non cambiavano, solo per farle restare visibili.

Con una transizione “scoped”, spesso questo problema si riduce drasticamente perché l’overlay è confinato.

Attenzione: il contenitore non si muove

C’è un trade-off importante: nella variante scoped, il contenitore che ospita l’overlay è un “confine”. Se vuoi che l’intero contenitore partecipi al movimento/trasformazione come gruppo, i nested view transition groups restano la soluzione più adatta.

Una regola empirica sensata oggi:

  1. provare prima con scoped view transitions quando serve isolamento e interattività,
  2. passare a nested groups quando serve fedeltà gerarchica, effetti corretti e trasformazioni complesse.

In arrivo: document.activeViewTransition

C’è anche un piccolo miglioramento di ergonomia in lavorazione: document.activeViewTransition, una proprietà che esporrà l’oggetto della transizione attiva (se presente).

È utile perché evita di dover conservare riferimenti manualmente quando avvii transizioni e vuoi agganciarti al loro lifecycle.

Sintesi e implicazione pratica

Le View Transitions stanno uscendo dalla fase “demo da conferenza” perché diventano più componibili e più robuste:

  • I types introducono una dimensione architetturale: transizioni scalabili, selettive, mantenibili.
  • match-element elimina molta burocrazia nelle liste e nelle UI ripetitive (con le dovute cautele nei framework che ricreano DOM).
  • I nested groups (Chrome 140) risolvono un problema strutturale: rispettare gerarchie ed effetti come ci aspettiamo dal layout reale.
  • Le scoped transitions promettono il salto di qualità per widget e sotto-UI, lasciando il resto della pagina utilizzabile e riducendo i classici problemi di overlay/z-index.

Se oggi stai progettando animazioni tra stati di UI, il consiglio pragmatico è: scegli un paio di flussi critici (paginazione, apertura pannelli, morph tra card e dettaglio) e implementali con View Transitions adottando subito types e una strategia coerente per i nomi (match-element + fallback via attr() quando possibile). Il risultato tende a essere più “nativo”, più comprensibile per l’utente e, soprattutto, più governabile nel tempo.