What's new in view transitions? (Google I/O 2024 update)

At Google I/O 2024, I announced the next step for view transitions: cross-document view transitions for multi-page applications (MPA).

On top of this, I shared some improvements that allow you to more easily work with view transitions in general.

  • Sharing animation styles between view transition pseudo-elements with view-transition-class.
  • Selective view transitions with active types.

These improvements apply to both same-document view transitions for single-page applications (SPA) and cross-document view transitions for MPA.

Cross-document view transitions for MPAs

Browser Support

  • 126
  • 126
  • x
  • x


In Chrome 111, the Chrome team shipped same-document view transitions for single-page applications, a well received feature within the web building community.

It's great to see what many of you have built with view transitions. Ranging from the typical implementations that "make the thumbnail grow into the big photo" to highly customized immersive experiences such as this one from Airbnb. Amazing!

A same-document view transition as seen on Airbnb.

However, the initial implementation required you to build an SPA in order to use view transitions. As of Chrome 126 this is no longer the case, view transitions are now enabled by default for same-origin navigations. You can now create a view transition between two different documents that are same-origin.

To enable cross-document view transitions, both ends need to opt-in. To do this, use the @view-transition at-rule and set the navigation descriptor to auto.

@view-transition {
  navigation: auto;

Cross-document view transitions use the same building blocks and principles as same-document view transitions. Elements with a view-transition-name applied are captured, and you can customize the animations using CSS animations.

To customize cross-document view transitions use the pageswap and pagereveal events, which give you access to the view transition object.

  • With pageswap you can do some last-minute changes on the outgoing page right before the old snapshots get taken.
  • With pagereveal you can customize the new page before it begins to render after it has been initialized.

In both events you have access to a NavigationActivation object to customize a cross-document view transition based on the old and new destination history entries, or the navigation type.

To top it off, you can wait for content to load with render blocking and rely on prerendering to improve the loading time before the view transition runs.


This Stack Navigator demo combines all of these features (along with some improvements).

Recording of the Stack Navigator demo. It uses cross-document view transitions that are customized in the pagereveal event based on navigation activation information. Prerendering is also used.

This is an MPA with cross-document navigations, hosted on the same origin. By using pagereveal, the type of animation is determined based on the old and new destination history entries.

window.addEventListener("pagereveal", async (e) => {
  if (e.viewTransition) {
    // Determine animation type based on the old/new history entries
    const transitionClass = determineTransitionClass(navigation.activation.from, navigation.currentEntry);
    document.documentElement.dataset.transition = transitionClass;

    // Cleanup after transition ran
    await e.viewTransition.finished;
    delete document.documentElement.dataset.transition;

Read the documentation

For more information on how to activate and customize cross-document view transitions, see our cross-document view transitions documentation.

View transitions improvements

Besides shipping cross-document view transitions for MPA, Chrome also includes a few refinements to working with view transitions in general.

These improvements apply to both same-document view transitions for SPA and cross-document view transitions for MPA.

Share animation styles with view-transition-class

Browser Support

  • 125
  • 125
  • x
  • x

Up until now, when animating multiple snapshots in the same way, you needed to target each and every snapshot individually by repeating its pseudo-selector for every element that has a unique view-transition-name.

With view-transition-class you can now add a shared name to all snapshots. Use this shared name in the pseudo selectors to target all snapshots that match. This results in far simpler selectors, which automatically scale from one to many elements.

#cards-wrapper > div {
  view-transition-class: card;
html::view-transition-group(.card) {
  animation-timing-function: var(--bounce);

The following cards example uses view-transition-class to apply the same animation timing to many snapshots using one selector.

Recording of the Cards demo. Using view-transition-class it applies the same animation-timing-function to all cards except the added or removed ones.

To find out more about view-transition-class, read the dedicated documentation on view-transition-class.

Selective view transitions with active types

Another refinement to view transitions is the introduction of adding types to a view transition when capturing and performing it. This makes it easier to work with various view transitions on the same page, without the declarations of the one changing the other.

For example, when going to the next or to the previous page in a pagination sequence, you might want to use different animations depending on whether you are going to a higher page or a lower page from the sequence.

Recording of the Pagination demo. Types determine which animation to use. Styles are separated in the style sheet thanks to active transition types.

Before active types, you could add classes to the DOM and respond to those classes in your CSS. However, you'd also have to cleanup after the transitions were complete.

With view transition types you can achieve the same result, with the added benefit of these types automatically getting cleaned up once the view transition has finished. Types only apply when capturing or performing the transition.

For same-document view transitions, pass the types into the startViewTransition method which now accepts an object. update is the callback function that updates the DOM, and types is a sequence of strings.

const direction = determineBackwardsOrForwards();

const t = document.startViewTransition({
  update: updateTheDOMSomehow,
  types: ['slide', direction],

For a cross-document view transition, set types in the @view-transition at-rule using the types descriptor or set them on the fly in the pageswap and pagereveal events.

@view-transition {
  navigation: auto;
  types: slide, forwards;

With the types set, you can respond to these types in your CSS using the :active-view-transition-type() and :active-view-transition pseudo-class selectors which apply to the view transition root.

/* Animation styles for forwards type only */
html:active-view-transition-type(forwards) {
  &::view-transition-old(content) {
    animation-name: slide-out-to-left;
  &::view-transition-new(content) {
    animation-name: slide-in-from-right;

To find out more about view transition types refer to the dedicated documentation for same-document view transitions and cross-document view transitions.


Developer feedback is always appreciated. To do so, file an issue with the CSS Working Group on GitHub with suggestions and questions. Prefix your issue with [css-view-transitions].

Should you run into a bug, then file a Chromium bug instead.