view-transition-scope CSS propertyExperimental: This is an experimental technology
Check the Browser compatibility table carefully before using this in production.
The view-transition-scope CSS property enables the discoverability of elements with view-transition-name values set on them (and therefore the creation of view transition snapshots) to be isolated to a specific element subtree.
/* Keyword values */
view-transition-scope: none;
view-transition-scope: all;
/* Global values */
view-transition-scope: inherit;
view-transition-scope: initial;
view-transition-scope: revert;
view-transition-scope: revert-layer;
view-transition-scope: unset;This property is specified as one of the following keyword values:
noneThe initial value. Discoverability of elements to snapshot during a view transition is not limited to any specific subtree.
allLimits the discoverability of elements to snapshot during a view transition to the subtree of the element on which this property is set. Only elements with a non-none view-transition-name are considered.
During the view transition process, the browser captures snapshots of elements that have a non-none view-transition-name set on them. These snapshots are then animated via CSS animations.
One issue that can arise during this process is naming collisions between elements involved in a view transition. You can't have the same view-transition-name set on multiple elements — if you do, the browser throws an InvalidStateError when the Element.startViewTransition() method is called to start the transition.
You could solve this problem by setting a view-transition-name of match-element on the elements to let the browser auto-assign internal unique names. However, this won't work if you are including multiple components from different sources that you don't control. A naming collision might still occur.
The view-transition-scope property allows view transitions to be self-contained. When view-transition-scope: all is set on an element, it limits the transition scope to that element and its descendants, which can be used to solve the above problem.
Whenever an element-scoped view transition is triggered, the browser automatically sets view-transition-scope: all on the transition root element, ensuring that only elements inside the transition scope are snapshotted and animated.
| Initial value | none |
|---|---|
| Applies to | all elements |
| Inherited | no |
| Computed value | as specified |
| Animation type | discrete |
view-transition-scope =
none |
all
view-transition-scope to isolate snapshotsThis example demonstrates how to use view-transition-scope to isolate the scope of document-scoped view transitions, enabling the same view-transition-name to be used on multiple elements.
The HTML includes a <button> element to control updating the DOM, plus several components with the class change-me, some of which are nested, all wrapped in a <section> element.
<button>Update DOM</button>
<section>
<div class="change-me"><span>I can change</span></div>
<div class="change-me">
<span>I can change</span>
<div class="change-me"><span>I can change</span></div>
</div>
<div class="change-me"><span>I can change</span></div>
</section>We start by setting the same view-transition-name on all components. We then set view-transition-scope: all on all of them, to isolate the view transition process for each one. Next, we set a longer animation-duration on all view transitions with this view-transition-name via the ::view-transition-group() pseudo-element.
.change-me {
background-color: white;
view-transition-name: para-change;
view-transition-scope: all;
}
::view-transition-group(para-change) {
animation-duration: 1s;
}The script starts by grabbing references to the button and the <div> elements (our components).
const btn = document.querySelector("button");
const divs = document.querySelectorAll("div");Next, we define a function called updateDivs(), which toggles the text content of each component's nested <span> element between two values, and also toggles the component's foreground and background colors between two values.
function updateDivs() {
divs.forEach((div) => {
if (div.firstElementChild.textContent === "I can change") {
div.firstElementChild.textContent = "I have changed";
div.style.color = "white";
div.style.backgroundColor = "black";
} else {
div.firstElementChild.textContent = "I can change";
div.style.color = "black";
div.style.backgroundColor = "white";
}
});
}Finally, we add a click event listener to the <button> element. When the button is clicked, we first check whether startViewTransition() exists on the document object — if it does not, we run updateDivs() and then return out of the function. This first part allows browsers that don't support view transitions to still update the DOM without error. Next, we run updateDivs() inside a startViewTransition() callback to trigger the view transition as the DOM updates.
btn.addEventListener("click", handleClick);
function handleClick(e) {
if (!document.startViewTransition) {
updateDivs();
return;
}
document.startViewTransition(() => {
updateDivs();
});
}Click the "Update DOM" button to see the view transition. Now try the following:
<div> elements.view-transition-scope: all; declaration to disable it.You should see that the view transition animation is not applied when the DOM changes, and an InvalidStateError is reported in the console.