Well well. Hello there. i know i am late to the party but view transitions api!! Thats some thing. i am hooked with it. Read up about it on CssWG spec for view transitions. Credits where due - Jake Archibald’s article helped me understand how view transitions api works.

The sample that i tried uses same document view transition. Lets walk through it. It is a simple transition from the grid view to list view

Card 1
Card 2
Card 3
Card 4
Card 5
Card 6
āž”ļø
Card 1
Card 2
Card 3
Card 4
Card 5
Card 6

Enabling view transition

View transitions are not enabled by default. We need to opt in using a bit of javascript like

// api check whether or not view transition is supported by browser
if(!document.startViewTransition) {
    return;
}

// it can very well be any element apart from document.
// Note that at the time of writing this blog, element level view transition is not yet supported in all the browsers.
// Check the link for more details - https://developer.mozilla.org/en-US/docs/Web/API/Element/startViewTransition
document.startViewTransition(() => {
    // Call back with layout changes applied
});

Lets get started.

i’ll start with a simple 2 x 3 grid using grid layout

.container {
  padding: 2rem;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1rem;
}

.card {
  padding: 1.5rem;
  background: #a2a2a2;
  border-radius: 8px;
  min-height: 150px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.2rem;
  font-weight: 500;
  color: var(--bg);
  text-shadow: none;
}

It looks like this

Card 1
Card 2
Card 3
Card 4
Card 5
Card 6

Let us see what our target view would be. We want to toggle the view to list view. So let me add style for that

.list-view {
  grid-template-columns: 1fr;
  overflow-y: auto;
  height: 316px;
  padding: 0;
}

It looks like

Card 1
Card 2
Card 3
Card 4
Card 5
Card 6

To toggle the view from grid to list, let me add a button and add a listener to it which enables the view transition

const toggleButton = document.getElementById('toggle-btn');
const container = document.getElementById('item-container');

toggleButton.addEventListener('click', () => {
    if(!container.startViewTransition) {
      container.classList.toggle('list-view');
      return;
    }

    container.startViewTransition(() => {
        container.classList.toggle('list-view');
    });
});
Card 1
Card 2
Card 3
Card 4
Card 5
Card 6

As you can see, the default view transition has a fade out and fade in effect for the container element. The old snapshot - the grid view, fades out and the new snapshot - the list view fades in. What if we wanted to change the default animation? Good news!! We can do that.

When the view transition is active, the browser adds a pseudo element tree specific to the view transition. Here is a sample pseudo element tree

View transition pseudo element tree

The default styles are applied to the root or document element unless we specify a view-transition-name.

To begin with, lets customize the animation time and function and add the following style

.container {
  ...
  view-transition-name: container;
}

::view-transition-group(container) {
  animation-duration: 2s;
  animation-timing-function: ease;
}

Lets see it in action

Card 1
Card 2
Card 3
Card 4
Card 5
Card 6

As you can see, the custom animation is applied as expected. To apply custom animation, i used the view-transition-name property to name view transition group. Accordingly browser added a ::view-transition-group(container) pseudo element which is used to apply the custom animation. The new tree looks like this

View transition pseudo element tree

While this works great, lets see how we can apply custom animation to individual elements. Using a different view-transition-name for each element can help us achieve this but that can be tedious. Worry not, there is a better way to let the browser give an auto-generated name to each groupelement using the match-element value like this

.card {
  ...
  view-transition-name: match-element;
}

Lets see it in action

Card 1
Card 2
Card 3
Card 4
Card 5
Card 6

As you can see, the custom animation is applied to each element as expected. And overall effect is not that bad either. Here is the new tree which has grown a bit in size šŸ˜€

View transition pseudo element tree

Now that you have a tree, try and apply custom animation to each element. Oh wait, how will you do it for all items with a randomly generated name? There is a way! Here’s how

::view-transition-group(*) {
  animation-duration: 2s;
  animation-timing-function: ease;
}

This will apply the custom animation to all the elements in all the view transition groups. This last bit you will have to do it for yourself and find out how that works out.

Hope you learned something new!