Uruchamianie równoczesnych i zagnieżdżonych przejść widoku za pomocą przejść widoku w zakresie elementu

Data publikacji: 27 marca 2026 r.

Przejścia widoku w zakresie elementu umożliwiają jednoczesne uruchamianie wielu przejść widoku, zagnieżdżanie trwających przejść widoku w innych oraz rozwiązywanie z-index problemów, które mogą wystąpić w przypadku przejść widoku w zakresie dokumentu. Jednocześnie reszta strony pozostaje interaktywna. Z tego przewodnika dowiesz się, jak z nich korzystać.

Film promocyjny: odkryj na nowo internet dzięki przejściom widoku o ograniczonym zakresie. Wypróbuj wersję demonstracyjną na żywo (Chrome 147 lub nowszy)

Potrzeba bardziej szczegółowych przejść widoku zakresu

Gdy rozpoczniesz przejście do widoku w tym samym dokumencie za pomocą document.startViewTransition() (lub jego odpowiednika w innym dokumencie), przeglądarka ograniczy zakres przejścia do widoku do dokumentu.

Gdy funkcja wywołania zwrotnego aktualizacji zostanie wykonana, a przeglądarka utworzy migawki wszystkich niezbędnych elementów, wynikowa ::view-transitionnakładka i jej drzewo pseudoelementów zostaną dołączone do elementu :root, html w tym przykładzie.

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

Ponieważ warstwa ::view-transition jest renderowana na wierzchu elementu głównego przejścia, może to prowadzić do nieoczekiwanych sytuacji. Na przykład elementy biorące udział w przejściu widoku mogą nagle nakładać się na inne elementy, które nie biorą w nim udziału, lub elementy mogą nie być już przycinane przez element nadrzędny podczas przejścia widoku.

Prezentacja na żywo

Nagranie demonstracyjne

Ponowne włączenie pointer-events na ::view-transition lub użycie zagnieżdżonych grup przejść widoku może rozwiązać niektóre efekty uboczne, które wprowadzają przejścia widoku w zakresie dokumentu. Nie wszystkie problemy można jednak rozwiązać za pomocą tych metod.

Na przykład elementy z position: fixed lub wyskakujące okienka są nadal zasłonięte przez przejście widoku w zakresie dokumentu, gdy przejście jest aktywne – znane również jako problem z z-index.

Włącz wyskakujące okienko w poniższej wersji demonstracyjnej, a następnie kliknij przycisk Shuffle (Tasuj), aby rozpocząć przejście widoku w zakresie dokumentu. Zagnieżdżone grupy przejść widoku rozwiązują problem z przycinaniem, ale problem z warstwami pozostaje.

Prezentacja na żywo

Nagranie demonstracyjne

Jednym z rozwiązań jest przechwycenie popover w ramach przejścia widoku przez nadanie mu view-transition-name. W przypadku jednej instancji może to działać, ale utrzymanie takiego rozwiązania jest uciążliwe i niepotrzebnie obciąża proces tworzenia migawek.

Przejścia widoku w zakresie elementu

Przejścia w formie obejrzenia w zakresie elementu umożliwiają rozpoczęcie przejścia w formie obejrzenia w poddrzewie DOM. Zamiast wywoływać funkcję document.startViewTransition(), wywołujesz funkcję element.startViewTransition() na dowolnym elemencie, co ogranicza przejście widoku do tego elementu.

W poniższym fragmencie kodu przeglądarka rozpoczyna przejście w formie obejrzenia w zakresie elementu w przypadku elementu <ul>.

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

Element, w którym wywołujesz element.startViewTransition(), np. <ul>, jest nazywany korzeniem przejścia lub zakresem.

Gdy przeglądarka ogranicza przejście widoku do elementu, jest on odizolowany od reszty DOM:

  • Przeglądarka szuka elementów do zrzutu tylko w drzewie podrzędnym zakresu.
  • Podczas tworzenia migawki – gdy wykonywane jest wywołanie zwrotne update – zatrzymane jest tylko renderowanie zakresu.
  • Powstałe pseudodrzewo ::view-transition jest wstrzykiwane do korzenia przejścia.

Na przykład w przypadku <ul> drzewo DOM wygląda tak, gdy przejście widoku jest aktywne:

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

Pseudoelement ::view-transition ma taki sam rozmiar i kształt jak element główny przejścia i jest renderowany tylko na nim. Dlatego kolejność warstw elementów poza katalogiem głównym przejścia jest zachowana.

Jeśli na przykład masz wyskakujące okienko widoczne nad elementem <ul>, a następnie rozpoczniesz przejście widoku w zakresie elementu <ul>, wyskakujące okienko nie zostanie zasłonięte przez pseudodrzewo przejścia widoku.

Wypróbuj to w poniższej wersji demonstracyjnej. Ma 2 przyciski. Pierwszy przycisk włącza i wyłącza wyskakujące okienko, a drugi zmienia kolejność elementów listy za pomocą przejścia widoku w zakresie elementu.

Prezentacja na żywo

Nagranie demonstracyjne

Ponieważ używane są przejścia widoku w zakresie elementu, wyskakujące okienko pozostaje widoczne nad elementem <ul>, gdy przejście jest aktywne.

Ponadto elementy znajdujące się poza elementem <ul>, np. przyciski, pozostają interaktywne, ponieważ nie należą do zakresu.

Zakresy uczestniczące w przejściach i zagnieżdżone grupy przejść widoku

Gdy rozpoczniesz przejście widoku z zakresem na element, który przycina zawartość (czyli gdy jego właściwość overflow jest ustawiona na hidden, scroll lub clip), zauważysz, że zawartość przejścia widoku pozostaje wizualnie przycięta.

Dzieje się tak, ponieważ przejścia widoku w zakresie elementu automatycznie obsługują te kwestie:

  • Zakres jest automatycznie view-transition-name: root stosowany, co sprawia, że sam w sobie uczestniczy w programie.
  • Zakres jest automatycznie view-transition-group: contain stosowany, aby włączyć zagnieżdżone grupy przejść widoku.
  • Powstały element ::view-transition-group-children(root) automatycznie przycina zawartość za pomocą overflow: clip, jeśli element główny zakresu przycina przepełnienie, co zapobiega wizualnemu wyciekaniu elementów pseudo poza element główny przejścia.

Dzięki temu możesz zachować styl CSS używany w przypadku przejść między widokami ograniczonych do elementów, które chcesz przechwycić. Na przykład w demonstracji listy CSS dodaje tylko nazwy do elementów listy:

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

Wypróbuj to w poniższej wersji demonstracyjnej. Umożliwia to zastąpienie samodzielnego uczestnictwa. Jeśli zakres to samodzielne uczestnictwo (domyślne działanie), wszystko działa zgodnie z oczekiwaniami. Gdy zakres nie jest samodzielny, jego obramowanie natychmiast się zmienia, a jego zawartość wykracza poza element opakowujący podczas przejścia.

Prezentacja na żywo

Nagranie demonstracyjne

Przykładowe drzewo pseudo dla tej wersji demonstracyjnej z udziałem własnym wygląda tak:

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

Ponieważ element główny przejścia, czyli element <ul>, pionowo przycina zawartość, element ::view-transition-group-children(root) również automatycznie stosuje przycinanie.

Równoczesne przejścia widoku w zakresie elementu

Przejścia widoku w zakresie elementu działają w izolacji, więc jeśli mają inny zakres, mogą działać jednocześnie.

W tym przykładzie są 2 przyciski zmiany kolejności – po jednym dla każdej listy. Każdy przycisk rozpoczyna przejście widoku w zakresie elementu tylko na odpowiedniej liście. Drzewa DOM obu list nie nakładają się na siebie, więc 2 przejścia widoku o zakresie elementu mogą działać jednocześnie w izolacji.

Prezentacja na żywo

Nagranie demonstracyjne

Dzięki temu możesz też ponownie używać wartości view-transition-name w różnych zakresach. Dopóki nazwa jest unikalna w swoim zakresie, nie ma konfliktu.

Zagnieżdżone przejścia widoku w zakresie elementu i zawieranie nazwy przejścia widoku

Gdy drzewa DOM wielu przejść widoku o zakresie obejmującym element nakładają się na siebie, istnieje ryzyko kolizji wartości view-transition-name. Z tego powodu przeglądarka automatycznie przypisuje wartość view-transition-scope: all do aktywnych przejść widoku w zakresie elementu, aby zmniejszyć to ryzyko.

Podobnie jak anchor-scope określa zakres wartości anchor-name, właściwość view-transition-scope zapewnia, że wartości view-transition-name są ograniczone do poddrzewa elementu. Właściwość akceptuje none, czyli listę nazw, które chcesz objąć zakresem, lub all, aby objąć zakresem wszystkie wartości.

Oprócz zapobiegania wyciekaniu nazw view-transition-scope zapobiega też przechwytywaniu elementu i jego zawartości przez zewnętrzne, równoczesne przejście widoku. Gdy proces tworzenia zrzutu przechodzi przez poddrzewo, aby znaleźć element do zrzutu, ignoruje elementy (i całe poddrzewo), do których zastosowano atrybut view-transition-scope: all. Zakładamy, że te elementy uczestniczą już w innym przejściu w formie obejrzenia ograniczonym do elementu.

Poniższa wersja demonstracyjna jest odmianą poprzedniej. Oprócz 2 przycisków, które losowo zmieniają kolejność elementów na liście, ma też przycisk Zamień, który umożliwia zamianę list. Przełączanie klasy .reversed na #lists-wrapper powoduje zamianę.

Prezentacja na żywo

Nagranie demonstracyjne

Ponieważ view-transition-scope: all jest stosowane automatycznie podczas przejścia do losowego odtwarzania, możesz rozpocząć równoczesne, zewnętrzne przejście zamiany, gdy przejście do losowego odtwarzania jest w toku.

Ponieważ view-transition-scope: all uniemożliwia też wykonanie migawki elementu w zewnętrznym przejściu, w wersji demonstracyjnej dodano też wartości view-transition-name do elementów opakowujących elementy <ul>.

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

Pseudo-drzewo w tym przykładzie po rozpoczęciu losowego odtwarzania na drugiej liście i zamianie obu list wygląda tak:

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

Więcej informacji

Więcej informacji o przejściach widoku w zakresie elementu znajdziesz w wyjaśnieniu, specyfikacji css-view-transitions-2liście otwartych zmian w specyfikacji.