Isaac.

View Transitions

Cover Image for View Transitions
Isaac
Isaac

I'm not one to brag, but I can hold my own as a front-end developer. The twist is, I don't actually enjoy front-end work, more specifically, UI. Wrestling with styling for hours isn't my idea of fun. While building this site, I remembered view transitions was a thing and I was shamefully excited to try it out. So let me put you on to view transitions.

A couple of gotchas out of the way:

  • MPA transitions don't work in Firefox yet — SPA transitions do (I'm a Zen user and I'm sad)
  • This isn't meant to be an all-encompassing tutorial :D

What are view transitions?

Try clicking the "Isaac" heading. You'll be sent over to the home route and catch this animation in action:

That is a multi-page view transition. In essence, the browser takes a snapshot of elements with a view-transition-name on the old page, then matches them with elements on the new page that share the same view-transition-name.

Single-page apps work the same, but instead of snapping between pages, you wrap your DOM changes in a callback. The browser compares the before and after, then animates the difference for you.

document.addEventListener("DOMContentLoaded", () => {
  let toggle = false;
  const container = document.querySelector(".container");
  const button = document.querySelector("button");
 
  button.addEventListener("click", () => {
    toggle = !toggle;
    document.startViewTransition(() => {
      if (toggle) {
        container.classList.add("move");
      } else {
        container.classList.remove("move");
      }
    });
  });
});

The trick is to add a view-transition name to each element you want to animate; if not, you get this funky animation:

.container {
  view-transition-name: container;
  width: fit-content;
  display: flex;
  gap: 20px;
}

When you add a transition name to the text, button, and link, each element will be tracked:

.container {
  view-transition-name: container;
  ...
}
 
button {
  view-transition-name: ele;
}
 
a {
  view-transition-name: link;
}
 
.text {
  view-transition-name: text;
}
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>View Transitions Demo</title>
    <link href="styles.css" rel="stylesheet" />
  </head>
  <body>
    <div class="container">
      <div>some content</div>
      <button>try it</button>
    </div>
  </body>
  <script src="./logic.js" defer></script>
</html>

For multi-page transitions you don't need JavaScript at all. Just add this to your CSS on both pages:

@view-transition {
  navigation: auto;
}

Any elements with matching view-transition-name values across pages will glide smoothly between their spots:

That's the gist of it. View transitions turn jarring state changes and navigation events into smooth animations with minimal effort. For a deeper dive, check out the MDN docs.