Запускайте одновременные и вложенные переходы между представлениями с использованием переходов между представлениями, ограниченных областью видимости элемента.

Опубликовано: 27 марта 2026 г.

Переходы между представлениями, ограниченные областью видимости элемента, позволяют одновременно запускать несколько переходов, вкладывать текущие переходы между ними и устраняют проблемы z-index , которые могут возникнуть при переходах между представлениями, ограниченных областью видимости документа, — и все это при сохранении интерактивности остальной части страницы. Прочитайте это руководство, чтобы узнать, как их использовать.

Рекламный ролик: Переосмыслите веб с помощью переходов в режиме ограниченного просмотра. Попробуйте демо-версию (Chrome 147 или более поздняя версия).

Необходимость более узконаправленных переходов между точками зрения.

Когда вы запускаете переход между представлениями в рамках одного документа с помощью document.startViewTransition() (или его аналога для перехода между документами ), браузер ограничивает область действия результирующего перехода только этим документом.

После выполнения функции обратного вызова обновления и создания браузером снимков всех необходимых элементов, результирующее наложение ::view-transition и его дерево псевдоэлементов прикрепляются к элементу :root , в следующем примере html .

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

Поскольку слой ::view-transition отрисовывается поверх корневого элемента перехода, это может привести к неожиданным ситуациям. Например, элементы, участвующие в переходе представления, могут внезапно перекрывать другие элементы, не участвующие в нем, или элементы могут перестать обрезаться своим родительским элементом-оберткой во время перехода представления.

Живая демонстрация

Демо-запись

Повторное включение pointer-events для ::view-transition или использование вложенных групп переходов между представлениями может устранить некоторые побочные эффекты, возникающие при переходах между представлениями в рамках документа. Однако эти методы не могут решить все проблемы.

Например, элементы с position: fixed или popovers остаются скрытыми при переходе между представлениями, ограниченном областью видимости документа, пока этот переход активен — это также известно как проблема z-index .

В следующем примере откройте всплывающее окно, а затем выберите кнопку « Перемешать» , чтобы запустить переход между представлениями в рамках всего документа. Вложенные группы переходов между представлениями решают проблему обрезки, но проблема наложения слоев остается.

Живая демонстрация

Демо-запись

Один из обходных путей — зафиксировать popover как часть перехода между представлениями, присвоив ему view-transition-name . Хотя это может сработать для одного экземпляра, такой подход сложен в поддержке и излишне нагружает процесс создания снимков состояния.

Переходы между представлениями, ограниченные областью видимости элемента.

Переходы между элементами позволяют запускать переход между представлениями на поддереве DOM. Вместо вызова document.startViewTransition() , вы вызываете element.startViewTransition() для произвольного элемента, что ограничивает область действия перехода только этим элементом.

В следующем фрагменте кода браузер запускает переход между представлениями, ограниченный областью видимости элемента <ul> .

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

Элемент, в котором вызывается element.startViewTransition() — например, элемент <ul> — называется корневым элементом перехода или областью видимости.

Когда браузер ограничивает область действия перехода между элементами, он изолируется от остальной части DOM:

  • Браузер ищет элементы для создания снимка только в пределах поддерева, указанного в данной области видимости.
  • В процессе создания снимка — пока выполняется функция обратного вызова update — останавливается только отрисовка области видимости.
  • Полученное псевдодерево ::view-transition внедряется в корень перехода.

Например, при использовании <ul> дерево DOM выглядит следующим образом, пока активен переход между представлениями:

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

Псевдоэлемент ::view-transition имеет тот же размер и форму, что и корневой элемент перехода, и отображается только поверх него. Благодаря этому соблюдается порядок наложения элементов, находящихся за пределами корневого элемента перехода.

Например, если у вас есть всплывающее окно, видимое над элементом <ul> , и затем вы запускаете переход между элементами с областью видимости элемента <ul> , всплывающее окно не будет перекрыто псевдодеревом перехода между элементами.

В следующем примере попробуйте сами. Здесь две кнопки. Первая кнопка переключает всплывающее окно, а вторая изменяет порядок элементов списка с помощью перехода между элементами, ограниченного областью видимости элемента.

Живая демонстрация

Демо-запись

Поскольку используются переходы между элементами, всплывающее окно остается видимым поверх элемента <ul> , пока активен переход.

Кроме того, элементы, находящиеся за пределами элемента <ul> , например, кнопки, остаются интерактивными, поскольку эти элементы не входят в область видимости.

Самостоятельно участвующие области видимости и вложенные группы переходов между представлениями

Когда вы запускаете анимацию перехода, ограниченную областью видимости элемента, для элемента, у которого обрезается содержимое (то есть, когда для overflow установлено значение hidden , scroll или clip ), вы замечаете, что содержимое анимации перехода визуально остается обрезанным.

Это происходит потому, что переходы между элементами представления обрабатываются автоматически следующим образом:

  • Область видимости автоматически получает view-transition-name: root , что делает её самоучаствующей.
  • Область видимости автоматически получает свойство view-transition-group: contain , позволяющее включить вложенные группы переходов между представлениями .
  • В результате псевдообъект ::view-transition-group-children(root) автоматически обрезает свое содержимое с помощью overflow: clip если корневая область видимости обрезает свое переполнение, что предотвращает визуальное распространение псевдообъектов за пределы корневой области перехода.

В результате вы можете использовать CSS-код для переходов между элементами, сфокусированный только на тех элементах, которые вы хотите захватить. Например, в демонстрационном примере со списком CSS-код добавляет к элементам списка только имена:

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

В следующем примере попробуйте это. Это позволяет переопределить самоуправление. Когда область видимости самоуправляется (поведение по умолчанию), всё работает как положено. Когда область видимости не самоуправляется, её граница немедленно изменяется, и её содержимое выходит за пределы контейнера во время перехода.

Живая демонстрация

Демо-запись

Для справки, псевдодерево для этой демонстрации с самостоятельным участием выглядит следующим образом:

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

Поскольку корневой элемент перехода, элемент <ul> , обрезает свое содержимое по вертикали, ::view-transition-group-children(root) также автоматически применяет обрезку.

Одновременные переходы между представлениями, ограниченными областью видимости элемента.

Поскольку переходы между представлениями, ограниченные областью видимости элемента, выполняются изолированно, несколько таких переходов могут выполняться одновременно, если у них разная область видимости.

В приведенном ниже примере используются две кнопки изменения порядка элементов, по одной для каждого списка. Каждая кнопка запускает переход между элементами только для соответствующего списка. Поскольку DOM-деревья обоих списков не перекрываются, два перехода между элементами могут выполняться одновременно и изолированно.

Живая демонстрация

Демо-запись

Такая изолированность также позволяет повторно использовать значения view-transition-name в разных областях видимости. Пока имя остается уникальным в пределах своей области видимости, конфликтов не возникает.

Вложенные переходы между представлениями с областью видимости элемента и включение имени перехода между представлениями

Когда DOM-деревья нескольких переходов между представлениями с областью видимости отдельных элементов перекрываются, возникает риск конфликта значений view-transition-name . По этой причине браузер автоматически присваивает активным переходам между представлениями с областью видимости отдельных элементов view-transition-scope: all чтобы снизить этот риск.

Подобно тому, как anchor-scope ограничивает область видимости значений anchor-name , свойство view-transition-scope гарантирует, что значения view-transition-name будут ограничиваться поддеревом элемента. Свойство принимает значения none (список имен, которые вы хотите ограничить областью видимости) или all (все значения).

Помимо предотвращения распространения имен, view-transition-scope также предотвращает захват элемента и его содержимого внешним, параллельным переходом представления. Когда процесс создания снимка проходит по поддереву в поисках элемента для создания снимка, он игнорирует элементы (и все их поддеревья), к которым применено свойство view-transition-scope: all . Это предполагает, что эти элементы уже участвуют в переходе представления с областью видимости другого элемента.

Следующая демонстрация — это вариация предыдущей. В дополнение к двум кнопкам, которые перемешивают содержимое списка, она также имеет кнопку «Поменять местами» для обмена списками. Переключение класса .reversed на объекте #lists-wrapper отвечает за обмен.

Живая демонстрация

Демо-запись

Поскольку свойство view-transition-scope: all автоматически применяется во время перехода перемешивания, вы можете запустить параллельный внешний переход обмена, пока переход перемешивания еще продолжается.

Поскольку свойство view-transition-scope: all также предотвращает создание снимка элемента во внешнем переходе, в демонстрации также добавляются значения view-transition-name к элементам, обертывающим элементы <ul> .

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

Псевдодерево для этой демонстрации, после начала перемешивания во втором списке и последующей замены обоих списков, выглядит следующим образом:

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

Узнать больше

Чтобы узнать больше о переходах между представлениями, ограниченных областью видимости элементов, см. пояснение , спецификацию css-view-transitions-2 и список открытых правок спецификации .