view-transition-name

Avatar of Geoff Graham
Geoff Graham on (Updated on )

The CSS view-transition-name property uniquely identifies an element that can be used in a view transition.

card {
  view-transition-name: card-transition;
}

We give the element a name (i.e., <custom-ident>) that we reference or set the property to none to exclude the element from view transitions.

The specification is not a standard just yet but describes view-transition-name as a way of “tagging individually transitioning subtrees” which is a super fancy way of saying we want a certain element to be captured in a view transition. When we give an element a view-transition-name, we’re effectively giving it access to a set of pseudo-elements for creating a view transition.

Syntax

view-transition-name: none | <custom-ident>;
  • Initial value: none
  • Applies to: All elements
  • Inherited: No
  • Percentages: N/A
  • Computed value: As specified
  • Canonical order: By grammar
  • Animation type: discreet

Property Values & Descriptions

/* <custom-ident> */
view-transition-name: banner;
view-transition-name: banner-transition;
view-transition-name: bannerTransition;

/* Keyword */
view-transition-name: none;
  • <custom-ident>: A unique identifier used to define an element that can participate in a view transition, whether it is the “old” element or the “new” one that is transitioned to. We can’t use the words none or auto for the value, as they are reserved global keyword values.
  • none: Removes the element from taking part in a view transition.

What the heck is a “captured element”?

It’s worth knowing because that’s exactly how the specification describes an element with a view-transition-name declared on it. The basic idea of view transitions is that we “capture” an existing state as an image and transition between that snapshot and a new element.

When we “capture” an element, we’re sort of tracking it during the lifetime of the view transition, during which the element takes multiple forms. Here’s the process that a captured element follows, as provided by the spec, which goes further by calling a captured element a “struct” or a set of items:

  • old image: A 2D bitmap or null. Initially null.
  • old width / old height: an unrestricted double, initially zero.
  • old transform: a <transform-function>, initially the identity transform function.
  • old writing-mode: Null or a writing-mode, initially null.
  • old direction: Null or a direction, initially null.
  • old text-orientation: Null or a text-orientation, initially null.
  • old mix-blend-mode: Null or a mix-blend-mode, initially null.
  • old backdrop-filter: Null or a backdrop-filter, initially null.
  • old color-scheme: Null or a color-scheme, initially null.
  • new element: An element or null. Initially null.

Those are all the pieces of a captured element used in a view transition. We capture a set of information about an element’s current (or “old”) state and transition it into a new element.

The name has to be unique

We can name a view transition anything we want (none and auto being the only exceptions) but it has to be unique in the sense that it is only applied to one rendered element on the current page.

The key word there is “rendered” because we can technically repurpose the same view-transition-name on multiple elements. For example, you might want the same transition on a set of images but wouldn’t want to go through the work of naming each and every one. We can instead declare view-transition-name on a certain class:

.image-transition {
  view-transition-name: image-zoom;
}

Then we can set up JavaScript that that sets a variable for each image in the set, adds the .image-transition class to the images, then triggers the transition with some action — like a click handler — on the image. From there, the script waits for the transition to wrap up, then removes the .image-transition class so it can be applied to another clicked image.

// Create a variable for img elements in a .gallery
const image = document.querySelectorAll(".gallery img");

// When an image is clicked...
image.onclick = () => {
  // If view transitions are *not* supported
  if (!document.startViewTransition) {
    // Run a fallback function
    doSomething(image);
  // If view transitions are supported
  } else {
    // Add the .image-transition class to the clicked image
    image.classList.add("image-transition");

    // Start the transition and save its instance in a variable
    const transition = document.startViewTransition(() => doSomething(image));

    // Wait for the transition to finish.
    await transition.finished;

    // Remove the class when finished
    image.classList.remove("image-transition");
  }
};

Another approach is to set view-transition-name to a <custom-ident> on the clicked image, wait for the transition to run, then swap out the <custom-ident> with the none value instead.

// Create a variable for img elements in a .gallery
const image = document.querySelectorAll(".gallery img");

// When an image is clicked...
image.onclick = () => {
  // First, check if view transitions are supported
  if (!document.startViewTransition) {
    // Fallback if View Transitions API is not supported.
    doSomething(image);
  } else {
    // Set `view-transition-name` with a <custom-ident>
    image.style.viewTransitionName = "image-zoom";

    // Start the transition and save its instance in a variable
    const transition = document.startViewTransition(() => doSomething(image));

    // Wait for the transition to finish.
    await transition.finished;

    // Set the transition name to `none` when finished
    image.style.viewTransitionName = "none";
  }
};

Specification

The view-transition-name property is just one of several view-* properties that are used together to register and manage view transitions that are part of the View Transitions Module Level 1 specification, which is currently a Candidate Recommendation Snapshot meaning it can be used where available, but is in the process of collecting feedback before formal recommendation. In other words, view-transition-name and other related properties are experimental and not part of the standards just yet.

Browser support

It’s only Chrome and other Chromium-powered browsers at the moment. Keep an eye on the Caniuse pages for the most current support information for the view-transition-name property and support for the none value.

Data on support for the view-transitions feature across the major browsers from caniuse.com

As far as browser support goes, we can use the view-transition-name property to check whether or not the user’s browser supports the View Transitions API and provide a fallback for browsers that lack support. We could use a <custom-ident> value to check support, but the none value is probably a better bet since it is a consistent keyword and we definitely want that value supported if we’re working with view trasnsitions anyway.

/* If the View Transitions API is supported */
@supports (view-transition-name: none) {

}

/* If the View Transitions API is *not* supported */
@supports not (view-transition-name: none) {
  /* Use a simple CSS animation if possible */
}

Similarly, we can check for support via JavaScript as well:

// If the View Transitions API is *not* supported.
if (!document.startViewTransition) {
  doSomething());

// Otherwise, start the view transition 
} else {
  document.startViewTransition(() => doSomething());
}