Esegui transizioni di visualizzazione simultanee e nidificate con transizioni di visualizzazione con ambito elemento

Data di pubblicazione: 27 marzo 2026

Le transizioni di visualizzazione con ambito elemento consentono di eseguire più transizioni di visualizzazione contemporaneamente, di nidificare le transizioni di visualizzazione in corso all'interno di un'altra e di risolvere i problemi di z-index che potresti riscontrare con le transizioni di visualizzazione con ambito documento, il tutto mantenendo interattivo il resto della pagina. Leggi questa guida per scoprire come utilizzarli.

Video promozionale: reimmagina il web con le transizioni di visualizzazione con ambito. Prova una demo dal vivo (Chrome 147 o versioni successive)

La necessità di transizioni di visualizzazione mirata con ambito più ristretto

Quando avvii una transizione di visualizzazione nello stesso documento con document.startViewTransition() (o tramite la relativa controparte cross-documento), il browser limita la transizione di visualizzazione risultante al documento.

Dopo l'esecuzione del callback di aggiornamento e lo snapshot di tutti gli elementi necessari da parte del browser, l'overlay ::view-transition e il relativo albero di pseudo-elementi vengono collegati all'elemento :root, html nell'esempio seguente.

html
  ├─ ::view-transition
  │  └─ ::view-transition-group(root)
  │     └─ ::view-transition-image-pair(root)
  │        ├─ ::view-transition-old(root)
  │        └─ ::view-transition-new(root)
  ├─ head
  └─ body
     └─ …

Poiché il livello ::view-transition viene visualizzato sopra la radice della transizione, ciò può portare a situazioni impreviste. Ad esempio, gli elementi che partecipano a una transizione di visualizzazione potrebbero sovrapporsi improvvisamente ad altri non partecipanti oppure gli elementi potrebbero non essere più ritagliati dal wrapper principale durante la transizione di visualizzazione.

Demo live

Registrazione demo

La riattivazione di pointer-events su ::view-transition o l'utilizzo di gruppi di transizione di visualizzazione nidificati può risolvere alcuni effetti collaterali introdotti dalle transizioni di visualizzazione con ambito documento. Tuttavia, questi metodi non possono risolvere tutti i problemi.

Ad esempio, gli elementi con position: fixed o i popup sono ancora oscurati da una transizione di visualizzazione con ambito documento mentre la transizione è attiva, nota anche come problema z-index.

Attiva/disattiva il popover nella demo seguente, quindi seleziona il pulsante Shuffle per avviare una transizione di visualizzazione con ambito documento. I gruppi di transizione della visualizzazione nidificati risolvono il problema di ritaglio, ma il problema di layering rimane.

Demo live

Registrazione demo

Una soluzione alternativa consiste nell'acquisire popover come parte della transizione della visualizzazione assegnandogli un view-transition-name. Anche se questo approccio potrebbe funzionare per una singola istanza, è difficile da gestire e sovraccarica inutilmente il processo di creazione degli snapshot.

Transizioni di visualizzazione con ambito elemento

Le transizioni di visualizzazione con ambito elemento ti consentono di avviare una transizione di visualizzazione su un sottoalbero del DOM. Anziché chiamare document.startViewTransition(), chiami element.startViewTransition() su un elemento arbitrario, che limita la transizione della visualizzazione a quell'elemento.

Nel seguente snippet, il browser avvia una transizione Visualizzazione con ambito elemento sull'elemento <ul>.

document.querySelector('ul').startViewTransition({
  callback: () => {
    // … code that manipulates the contents of <ul>
  },
})

L'elemento in cui richiami element.startViewTransition(), ad esempio <ul>, è chiamato radice della transizione o ambito.

Quando il browser limita una transizione di visualizzazione a un elemento, questo viene isolato dal resto del DOM:

  • Il browser cerca gli elementi da acquisire solo all'interno della sottostruttura dell'ambito.
  • Durante il processo di creazione dello snapshot, mentre viene eseguito il callback update, viene interrotta solo la visualizzazione dell'ambito.
  • Lo pseudo-albero ::view-transition risultante viene inserito nella radice della transizione.

Ad esempio, con <ul>, l'albero DOM ha il seguente aspetto mentre la transizione di visualizzazione è attiva:

html
  ├─ head
  └─ body
     ├─ ul
     │  ├─ ::view-transition
     │  │  └─ ::view-transition-group(root)
     │  │     ├─ ::view-transition-group-children(root)
     │  │     │  └─ …
     │  │     └─ ::view-transition-image-pair(root)
     │  │        ├─ ::view-transition-old(root)
     │  │        └─ ::view-transition-new(root)
     │  ├─ li
     │  ├─ li
     │  └─ li
     ├─ button#showpopover
     ├─ button#reorder
     └─ div#popover
        └─ p

Lo pseudo-elemento ::view-transition ha le stesse dimensioni e la stessa forma della radice della transizione e viene visualizzato solo sopra la radice della transizione. Per questo motivo, l'ordine di sovrapposizione degli elementi al di fuori della radice della transizione viene rispettato.

Ad esempio, se hai un popover visibile sopra l'elemento <ul> e poi avvii una transizione di visualizzazione con ambito elemento sull'elemento <ul>, il popover non viene oscurato dallo pseudo-albero della transizione di visualizzazione.

Prova nella demo seguente. Ha due pulsanti. Il primo pulsante attiva/disattiva il popover, mentre il secondo riordina gli elementi dell'elenco utilizzando una transizione di visualizzazione con ambito elemento.

Demo live

Registrazione demo

Poiché vengono utilizzate transizioni di visualizzazione con ambito elemento, il popup rimane visibile sopra l'elemento <ul> mentre la transizione è attiva.

Inoltre, gli elementi al di fuori dell'elemento <ul>, ad esempio i pulsanti, rimangono interattivi perché non fanno parte dell'ambito.

Ambiti di partecipazione automatica e gruppi di transizione delle visualizzazioni nidificati

Quando avvii una transizione di visualizzazione con ambito elemento su un elemento che taglia il relativo overflow (ovvero quando la proprietà overflow è impostata su hidden, scroll o clip), noti che i contenuti della transizione di visualizzazione rimangono visivamente tagliati.

Questo perché le transizioni di visualizzazione con ambito elemento gestiscono automaticamente quanto segue:

  • L'ambito viene applicato automaticamente, il che lo rende autogestito.view-transition-name: root
  • L'ambito viene applicato automaticamente per abilitare i gruppi di transizione di visualizzazione nidificati.view-transition-group: contain
  • Lo pseudo ::view-transition-group-children(root) risultante ritaglia automaticamente i suoi contenuti utilizzando overflow: clip se la radice dell'ambito ritaglia il suo overflow, il che impedisce agli pseudo di fuoriuscire visivamente dalla radice della transizione.

Di conseguenza, puoi mantenere il CSS che utilizzi con le transizioni di visualizzazione con ambito elemento concentrato solo sugli elementi che vuoi acquisire. Ad esempio, nella demo dell'elenco, il CSS aggiunge solo nomi agli elementi dell'elenco:

ul li {
  view-transition-name: match-element;
  view-transition-class: album;
}

Prova nella demo seguente. Ti consente di ignorare la partecipazione personale. Quando l'ambito è autogestito (il comportamento predefinito), tutto funziona come previsto. Quando l'ambito non è autogestito, il relativo bordo cambia immediatamente e il contenuto esce dal wrapper durante la transizione.

Demo live

Registrazione demo

A titolo di riferimento, lo pseudo-albero per questa demo con autopartecipazione è il seguente:

html
  ├─ head
  └─ body
     ├─ ul
     │  ├─ ::view-transition
     │  │  └─ ::view-transition-group(root)
     │  │     ├─ ::view-transition-group-children(root)
     │  │     │  ├─ ::view-transition-group(item1)
     │  │     │  │  └─ ::view-transition-image-pair(item1)
     │  │     │  │     ├─ ::view-transition-old(item1)
     │  │     │  │     └─ ::view-transition-new(item1)
     │  │     │  ├─ ::view-transition-group(item2)
     │  │     │  │  └─ …
     │  │     │  …
     │  │     └─ ::view-transition-image-pair(root)
     │  │        ├─ ::view-transition-old(root)
     │  │        └─ ::view-transition-new(root)
     │  ├─ li
     │  ├─ li
     │  └─ li
     └─ button#reorder

Poiché la radice della transizione, l'elemento <ul>, taglia verticalmente i suoi contenuti, anche ::view-transition-group-children(root) applica automaticamente un taglio.

Transizioni di visualizzazione simultanee con ambito elemento

Poiché le transizioni di visualizzazione con ambito elemento vengono eseguite in isolamento, più transizioni di visualizzazione con ambito elemento possono essere eseguite contemporaneamente se hanno un ambito diverso.

La seguente demo ha due pulsanti di riordino, uno per ogni elenco. Ogni pulsante avvia una transizione di visualizzazione con ambito elemento solo nel rispettivo elenco. Poiché gli alberi DOM di entrambi gli elenchi non si sovrappongono, le due transizioni di visualizzazione con ambito elemento possono essere eseguite contemporaneamente in isolamento.

Demo live

Registrazione demo

Questa natura isolata ti consente anche di riutilizzare i valori view-transition-name in ambiti diversi. Finché un nome rimane univoco all'interno del suo ambito, non si verifica alcun conflitto.

Transizioni di visualizzazione con ambito elemento nidificato e contenimento di view-transition-name

Quando gli alberi DOM di più transizioni di visualizzazione con ambito elemento si sovrappongono, esiste il rischio di collisione dei valori view-transition-name. Per questo motivo, il browser assegna automaticamente view-transition-scope: all alle transizioni di visualizzazione con ambito elemento attive per mitigare questo rischio.

Analogamente al modo in cui gli ambiti anchor-scope limitano i valori anchor-name, la proprietà view-transition-scope garantisce che i valori view-transition-name siano limitati al sottoalbero dell'elemento. La proprietà accetta none, un elenco di nomi a cui vuoi applicare l'ambito, o all per applicare l'ambito a tutti i valori.

Oltre a impedire la fuoriuscita dei nomi, view-transition-scope impedisce anche l'acquisizione di un elemento e dei relativi contenuti da parte di una transizione di visualizzazione esterna e simultanea. Quando il processo di creazione dello snapshot attraversa l'albero secondario per trovare un elemento di cui creare lo snapshot, ignora gli elementi (e l'intero albero secondario) a cui è applicato view-transition-scope: all. Ciò presuppone che questi elementi partecipino già a una transizione Visualizzazione con ambito elemento diverso.

La seguente demo è una variante della precedente. Oltre ai due pulsanti che riproducono in ordine casuale i contenuti dell'elenco, è presente anche un pulsante Scambia per scambiare gli elenchi. L'attivazione/disattivazione di un corso .reversed sul #lists-wrapper gestisce lo scambio.

Demo live

Registrazione demo

Poiché view-transition-scope: all viene applicato automaticamente durante la transizione di riproduzione casuale, puoi avviare una transizione di scambio esterno simultanea mentre la transizione di riproduzione casuale è ancora in corso.

Poiché view-transition-scope: all impedisce anche che un elemento venga acquisito in una transizione esterna, la demo aggiunge anche valori view-transition-name agli elementi che racchiudono gli elementi <ul>.

#list1-wrapper, #list2-wrapper {
  view-transition-name: attr(id type(<custom-ident>));
}

Lo pseudo-albero per questa demo, dopo aver avviato la riproduzione casuale nella seconda lista e poi scambiato entrambe le liste, ha il seguente aspetto:

html
  ├─ head
  └─ body
     └─ #lists-wrapper.reversed (SCOPE)
        ├─ ::view-transition
        │  └─ ::view-transition-group(lists-wrapper)
        │     ├─ ::view-transition-group-children(lists-wrapper)
        │     │  ├─ ::view-transition-group(list1-wrapper)
        │     │  │  └─ ::view-transition-image-pair(list1-wrapper)
        │     │  │     ├─ ::view-transition-old(list1-wrapper)
        │     │  │     └─ ::view-transition-new(list1-wrapper)
        │     │  └─ ::view-transition-group(list2-wrapper)
        │     │     └─ ::view-transition-image-pair(list2-wrapper)
        │     │        ├─ ::view-transition-old(list2-wrapper)
        │     │        └─ ::view-transition-new(list2-wrapper)
        │     └─ ::view-transition-image-pair(lists-wrapper)
        │        ├─ ::view-transition-old(lists-wrapper)
        │        └─ ::view-transition-new(lists-wrapper)
        ├─ div#list1-wrapper
        │  ├─ ul
        │  │  ├─ li#item1
        │  │  ├─ li#item2
        │  │  └─ li#item3
        │  └─ button.reorder
        └─ div#list2-wrapper
           ├─ ul (SCOPE)
           │  ├─ ::view-transition
           │  │  └─ ::view-transition-group(list)
           │  │     ├─ ::view-transition-group-children(list    )
           │  │     │  ├─ ::view-transition-group(item4)
           │  │     │  │  └─ ::view-transition-image-pair(item4)
           │  │     │  │     ├─ ::view-transition-old(item4)
           │  │     │  │     └─ ::view-transition-new(item4)
           │  │     │  ├─ ::view-transition-group(item5)
           │  │     │  │  └─ …
           │  │     │  …
           │  │     └─ ::view-transition-image-pair(list)
           │  │        ├─ ::view-transition-old(list)
           │  │        └─ ::view-transition-new(list)
           │  ├─ li#item4
           │  ├─ li#item5
           │  └─ li#item6
           └─ button.reorder

Scopri di più

Per saperne di più sulle transizioni di visualizzazione con ambito elemento, consulta la spiegazione, le specifiche css-view-transitions-2 e l'elenco delle modifiche alle specifiche aperte.