view-transition-name
Baseline 2025Newly available
Since October 2025, this feature works across the latest devices and browser versions. This feature might not work in older devices or browsers.
Theview-transition-nameCSS property specifies theview transition snapshot that selected elements will participate in. This enables you to animate those elements separately from the rest of the page, which uses the default cross-fade animation during a view transition. You can then define custom animation styles for these elements.
In this article
Syntax
/* <custom-ident> value examples */view-transition-name: header;view-transition-name: figure-caption;/* Keyword value */view-transition-name: none;view-transition-name: match-element;/* Global values */view-transition-name: inherit;view-transition-name: initial;view-transition-name: revert;view-transition-name: revert-layer;view-transition-name: unset;Values
<custom-ident>An identifying name that causes the selected element to participate in a separate snapshot from the root snapshot. The
<custom-ident>cannot beauto,match-element,none, or aCSS-wide keyword value.match-elementThe browser automatically assigns a unique name to the selected element. This name is used to snapshot the element separately from all other elements on the page. (This name is internal and cannot be read from the DOM.)
noneThe selected element will not participate in a separate snapshot, unless it has a parent element with a
view-transition-nameset, in which case it will be snapshotted as part of that element.
Description
By default, when a view transition is applied to a web app, all changes to the UI that occur during that transition are snapshotted and animated together. This is the default — orroot — snapshot (seeThe view transition pseudo-element tree). By default, this animation is a smooth cross-fade, which can be seen in action in theView Transitions SPA demo.
If you want certain elements to be animated differently from theroot snapshot during the view transition, you can do so by giving them a differentview-transition-name, for example:
figcaption { view-transition-name: figure-caption;}You can then specify which animations you want for the before and after snapshots using the relevant view transition pseudo-elements —::view-transition-old() and::view-transition-new(). For example:
::view-transition-old(figure-caption) { animation: 0.25s linear both shrink-x;}::view-transition-new(figure-caption) { animation: 0.25s 0.25s linear both grow-x;}If you don't want an element to be snapshotted separately, you can specify aview-transition-name value ofnone:
.dont-animate-me { view-transition-name: none;}Theview-transition-name<custom-ident> must be unique for each rendered element taking part in the view transition. If two rendered elements have the sameview-transition-name at the same time, theViewTransition.readyPromise will reject and the transition will be skipped.
Specifyingview-transition-name values automatically
Sometimes you will want to animate multiple UI elements separately in a view transition. This is often the case when you have a list of elements on a page and want to rearrange them in some way:
<ul> <li>Item 1</li> <li>Item 2</li> <li>Item 3</li> <li>Item 4</li> <!-- ... --> <li>Item 99</li></ul>Giving each one a unique name can be inconvenient, especially as the number of elements gets larger:
li:nth-child(1) { view-transition-name: item1;}li:nth-child(2) { view-transition-name: item2;}li:nth-child(3) { view-transition-name: item3;}li:nth-child(4) { view-transition-name: item4;}/* ... */li:nth-child(99) { view-transition-name: item99;}To get around this problem, you can use thematch-element value, which causes the browser to give each selected element a unique internalview-transition-name:
li { view-transition-name: match-element;}Becausematch-element assigns automaticview-transition-name values based on element identity, it can only be used for same-document view transitions. The auto-generated internal identifiers are not transferrable across different elements or documents.
Formal definition
| Initial value | none |
|---|---|
| Applies to | all elements |
| Inherited | no |
| Computed value | as specified |
| Animation type | discrete |
Formal syntax
view-transition-name =
none|
<custom-ident>
Examples
>Basicview-transition-name usage
This example comes from theView Transitions SPA demo, which is a basic image gallery. TheBasic SPA view transition provides a more detailed explanation of how this demo works.
Most of the UI changes are animated using theroot transition snapshot. However, the<figcaption> is given aview-transition-name offigure-caption to allow it to be animated differently from the rest of the page:
figcaption { view-transition-name: figure-caption;}The following code applies a custom animation just to the<figcaption>:
@keyframes grow-x { from { transform: scaleX(0); } to { transform: scaleX(1); }}@keyframes shrink-x { from { transform: scaleX(1); } to { transform: scaleX(0); }}::view-transition-group(figure-caption) { height: auto; right: 0; left: auto; transform-origin: right center;}::view-transition-old(figure-caption) { animation: 0.25s linear both shrink-x;}::view-transition-new(figure-caption) { animation: 0.25s 0.25s linear both grow-x;}We create a custom CSS animation and apply it to the::view-transition-old(figure-caption) and::view-transition-new(figure-caption) pseudo-elements. We also apply other styles to keep them both in the same place and to stop the default styling from interfering with our custom animations.
Using thematch-element value
This example contains a list of technologies–HTML, CSS, SVG, and JS–that are displayed in a sidebar next to a main content area, which starts out empty. Clicking a technology's heading animates its content into the adjoining content area that shows more details.
HTML
The<main> element contains anunordered list and an<article> element. The multiple child<li> elements inside the list each contain an<a> element inside aheading.
<main> <ul> <li> <h2><a href="#">HTML</a></h2> <h3>HyperText Markup Language</h3> <p> HyperText Markup Language (HTML) is the most basic building block of the web. It defines the meaning and structure of web content. HTML provides the fundamental building blocks for structuring web documents and apps. </p> </li> <li> <h2><a href="#">CSS</a></h2> <h3>Cascading Style Sheets</h3> <p> Cascading Style Sheets (CSS) is a stylesheet language used to describe the presentation of a document written in HTML or XML (including XML dialects such as SVG, MathML or XHTML). CSS describes how elements should be rendered on screen, on paper, in speech, or on other media. </p> </li> <li> <h2><a href="#">SVG</a></h2> <h3>Scalable Vector Graphics</h3> <p> Scalable Vector Graphics (SVG) is an XML-based markup language for describing two-dimensional based vector graphics. </p> </li> <li> <h2><a href="#">JS</a></h2> <h3>JavaScript</h3> <p> JavaScript (JS) is the web's native programming language. JavaScript is a lightweight, interpreted (or just-in-time compiled) programming language with first-class functions. While it is most well-known as the scripting language for web pages, many non-browser environments, such as Node.js, also use it. </p> </li> </ul> <article></article></main><form> <label for="match-element-checkbox"> Apply <code>match-element</code> to list items? </label> <input type="checkbox" checked /></form>CSS
We useflexbox to lay out the<li> and the<article> side by side, and to make the list items share equal amount of space in the first column. The list takes up 35% of the container's width, while the<article> fills the remaining available horizontal space.
/* General styles and resets */* { box-sizing: border-box; font-size: 0.9rem;}html { font-family: "Helvetica", "Arial", sans-serif; height: 100%;}body { margin: 0; height: inherit; display: flex; flex-direction: column; justify-content: space-around;}li h2 { margin: 0;}ul { padding: 0; margin: 0; list-style-type: none;}li { overflow: hidden; container-type: inline-size;}li p { display: none;}li.active-item p { display: block;}li:nth-child(1) { background-color: #cbc0d3; border: 20px solid #cbc0d3;}li:nth-child(2) { background-color: #efd3d7; border: 20px solid #efd3d7;}li:nth-child(3) { background-color: #feeafa; border: 20px solid #feeafa;}li:nth-child(4) { background-color: #dee2ff; border: 20px solid #dee2ff;}/* Links */a { text-decoration: none; color: rgb(0 0 255 / 0.8);}a:hover,a:focus { color: rgb(100 100 255);}/* Form and checkbox styles */form { position: absolute; bottom: 0; right: 0; z-index: 2; background-color: white; padding: 10px; border: 1px solid black;}main { container-type: inline-size; width: 100%; height: 100%; display: flex; gap: 2cqw; position: relative;}ul { width: 35cqw; display: flex; flex-direction: column; gap: 1cqw;}article { flex: 1;}li { flex: 1;}We also define a rule that selects elements with theactive-item class. When this class is applied to an element, the rule causes it to be positioned exactly over the top of the<article> element. This class will be applied to the list items via JavaScript when their links are clicked, which will initiate a view transition.
.active-item { position: absolute; z-index: 1; translate: 37cqw; width: calc(100% - 37cqw); height: 100%;}By default, all elements in a view transition are animated together in a single cross-fade. In this example, however, we don't want this — we want each list item to have its own movement animation. We can achieve this by applyingview-transition-name: match-element to every list item:
.match-element-applied li { view-transition-name: match-element;}Thematch-element-applied class is applied to the<main> element by default, which is why the checkbox in the Result frame is initially selected. If you uncheck it, the class is removed and the default cross-fade animation comes into effect instead. You can toggle the checkbox to compare the default animation with the one applied whenview-transition-name: match-element is used.
Next, we customize the animation by using the::view-transition-group() pseudo-element to apply ananimation-duration to all the view transition groups (signified by the* identifier) and give all the old and new snapshots aheight of100%. This works around differences in the aspect ratios of the old and new snapshots and makes the animations look smoother:
::view-transition-group(*) { animation-duration: 0.5s;}html::view-transition-old(*),html::view-transition-new(*) { height: 100%;}JavaScript
In this example, theactive-item class is applied to the list items when their links are clicked; this is achieved via theupdateActiveItem() function:
const mainElem = document.querySelector("main");let prevElem;let checkboxElem = document.querySelector("input");// View transition codefunction updateActiveItem(event) { // Get the list item that contains the clicked link const clickedElem = event.target.parentElement.parentElement; // Set the active-item class on the list item clickedElem.className = "active-item"; // Keep track of the previous item that was clicked, if any. // Remove the active-item class from the previous item so that only // one list item is placed over the <article> at any one time if (prevElem === clickedElem) { prevElem.className = ""; prevElem = undefined; } else if (prevElem) { prevElem.className = ""; prevElem = clickedElem; } else { prevElem = clickedElem; }}mainElem.addEventListener("click", (event) => { event.preventDefault(); // Prevent iframe from scrolling when clicked // Do nothing unless a link is clicked inside the <main> element if (event.target.tagName !== "A") { return; } // Run updateActiveItem() on its own if view transitions are not supported if (!document.startViewTransition) { updateActiveItem(event); } else { // Run updateActiveItem() via startViewTransition() const transition = document.startViewTransition(() => updateActiveItem(event), ); }});// Toggle the class on <main> to control whether or not match-element is appliedcheckboxElem.addEventListener("change", () => { mainElem.classList.toggle("match-element-applied");});Running theupdateActiveItem() function via thestartViewTransition() function animates the display of technology details smoothly.
Result
Click a technology heading in the sidebar and notice the animation effect of its content into the main content area.
There is also a checkbox, which is selected by default, soview-transition-name: match-element is applied. Uncheck the checkbox and click a heading again to see how the view-transition works withoutview-transition-name: match-element.
Specifications
| Specification |
|---|
| CSS View Transitions Module Level 1> # view-transition-name-prop> |