---
title: "View Transitions: the smoothest thing the web shipped this year."
date: 2024-09-18
url: https://remiam.co.uk/notes/view-transitions-api-smoothest-thing
tags: [CSS, Web Standards, UX, Animation]
read_time_minutes: 8
description: "The View Transitions API in 2024 — what it does, how to use it, browser support, code examples, and why it makes the web feel finally as smooth as a native app."
---

# View Transitions: the smoothest thing the web shipped this year.

*Published 2024-09-18 · 8 min read · by Liam (Remiam)*

Multi-page transitions that feel like a native app. Element-to-element morphs across navigations. The View Transitions API quietly became one of the best browser features in a decade — and replaces three libraries with twenty lines of CSS.

The View Transitions API hit broad browser support this year. It is the closest the web has ever felt to a native app — and the surprising part is how easy it is to wire up. Two CSS properties and one JS call replace what used to take Framer Motion, AnimatePresence, or hand-rolled FLIP libraries.

## What it does

- Animates the transition between two states of the DOM, including across page navigations.
- Lets you tag elements as 'transition partners' so they morph from one page to the next.
- Browser handles the snapshot, the interpolation, and the cleanup — you write CSS animations and view-transition-name rules.
- Same-document (SPA) and cross-document (MPA) navigations are both supported.
- Respects prefers-reduced-motion automatically.

## Browser support

| Browser | Same-document | Cross-document |
| --- | --- | --- |
| Chrome 111+ | Stable | Stable in 126+ |
| Edge 111+ | Stable | Stable in 126+ |
| Safari 18+ | Stable | Coming |
| Firefox | Not yet | Not yet |

*View Transitions API browser support, September 2024.*

## A complete example, in plain HTML / CSS / JS

```html gallery.html (excerpt)
<a href="/photo/42" class="card" id="card-42">
  <img src="/img/42-thumb.jpg" class="card__image" />
  <h3 class="card__title">Sunset on the Ridge</h3>
</a>
```

```css gallery.css
/* Tag the elements that should morph between pages */
.card__image {
  view-transition-name: photo-42-image;
}
.card__title {
  view-transition-name: photo-42-title;
}

/* Customise the animation if you want non-default behaviour */
::view-transition-old(photo-42-image),
::view-transition-new(photo-42-image) {
  animation-duration: 0.5s;
  animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
```

```typescript router.ts
// Same-document SPA navigation
async function navigateTo(url: string) {
  if (!document.startViewTransition) {
    // Fallback for unsupported browsers — just navigate
    location.href = url
    return
  }
  const transition = document.startViewTransition(async () => {
    await renderNewPage(url)
  })
  // Optionally wait for the animation to finish
  await transition.finished
}
```

## Where it's already paying off

- Listing → detail page transitions where the card expands into the hero. Used to need React + Framer Motion plus state mirroring; now it's a class name.
- Tabbed views that fade and shift without a full re-render.
- Modal opens that feel anchored to the element that triggered them.
- Image galleries — the thumbnail morphs into the lightbox view.
- Cross-page navigation on multi-page sites — the entire MPA suddenly feels like an SPA.

> It's the rare web feature that genuinely improved the platform without anyone needing a library to use it. Two CSS properties and a single browser API call replace a category of JavaScript dependency.

## What to watch for

- Same-document transitions are stable everywhere except Firefox; cross-document ones are still rolling out — feature-detect with if (document.startViewTransition).
- Reduced-motion users get unstyled transitions by default. Respect prefers-reduced-motion explicitly if your transitions are highly motion-driven.
- Don't animate every transition just because you can. Restraint is still the point.
- view-transition-name values must be unique per page. Listing pages with 20 cards need 20 unique names — use the item ID.
- Performance-sensitive transitions (many large elements) still benefit from will-change hints and minimal reflow.

## What this replaces

- Framer Motion AnimatePresence + layoutId patterns for shared element transitions.
- Hand-rolled FLIP (First, Last, Invert, Play) libraries.
- Some uses of GSAP Flip.
- Animation libraries shipped purely to handle page transitions.

We're now using View Transitions on every Nuxt project where the design calls for it. The amount of code it replaces is striking. It's a platform-level capability that finally caught up to what the design world has been asking for since the iPhone shipped its first ZUI animation in 2007.

## References

1. [MDN — View Transitions API](https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API)
2. [Web.dev — Smooth transitions with the View Transition API](https://developer.chrome.com/docs/web-platform/view-transitions)
3. [Can I Use — View Transitions support](https://caniuse.com/view-transitions)
