Skip to content

The publication for web craftspeople Tuesday, 25 August 2026

Front-end

View Transitions: smooth page transitions without a framework

The View Transitions API animates the move from one state to the next, within a single page or between two pages, with no animation library. This guide walks through both variants of the API, how to wire them up, and the real…

Illustration View Transitions sur dégradé bleu-vert, magazine Mail Studio
View Transitions — Mail Studio

For years, animating the move from one view to another meant a dedicated library and extra code. The View Transitions API moves that work into the browser: it takes a snapshot of the old state, a snapshot of the new one, and interpolates between them. It comes in two variants, one for single-page apps and one for navigation between pages, and it is safe to adopt thanks to clean degradation.

Two APIs under one name

The term covers two related but distinct mechanisms. The same-document transition applies when JavaScript edits the DOM in place, typically in a single-page app. The cross-document transition applies during a classic navigation from one URL to another, provided both pages share the same origin. Both rely on the same rendering engine and the same selectors, which keeps the learning curve short.

The good news fits on one line: if the browser cannot animate, the page still updates.

Animating a transition within one page

The entry point is document.startViewTransition. The function takes a callback that mutates the DOM; the browser captures the screen before the call, runs the callback, captures the screen after, then animates the swap. A feature check is enough to guarantee the fallback.

function mettreAJourVue(donnees) {
  // remplace le contenu du DOM ici
}

if (!document.startViewTransition) {
  mettreAJourVue(donnees);            // repli : mise a jour sans animation
} else {
  document.startViewTransition(() => mettreAJourVue(donnees));
}

With no customisation, the browser applies a cross-fade across the whole page. That alone helps for a tab change, a list sort or opening a panel, where a hard cut used to hurt readability.

Chaining two pages without JavaScript

The cross-document transition needs no script. It is enabled in CSS, on both pages involved, through an opt-in rule. Navigation must stay within the same origin; a link to another domain triggers no transition.

/* opt-in : transitions entre pages de meme origine */
@view-transition {
  navigation: auto;
}

From there, a plain click on an internal link produces a fade between the old and the new page, with no routing library or client-side rendering. For an editorial site or a shop built on classic pages, that is the most immediate win.

Carrying an element from one view to the next

The striking effect is morphing: a thumbnail image that grows into the header image of the next page, for instance. You simply give the same view-transition-name to the source element and the destination element. The browser understands it is the same object and animates it from one position to the other.

.carte-article img {
  view-transition-name: visuel-article;
}

::view-transition-old(visuel-article),
::view-transition-new(visuel-article) {
  animation-duration: 300ms;
}

Each name must be unique within a given view. The browser then generates a tree of pseudo-elements: ::view-transition-group(), ::view-transition-old() and ::view-transition-new(), which you target in CSS to tune duration, easing or path. The page root carries the reserved name root, which lets you customise the global fade.

Customising the animation and honouring preferences

Because the pseudo-elements are animated with ordinary CSS rules, the usual toolbox applies: animation, @keyframes, delays. The flip side is an accessibility duty: an over-emphatic animation bothers some users. The prefers-reduced-motion query must cut the transitions for anyone who asked for it.

@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) {
    animation: none !important;
  }
}

That precaution costs almost nothing and keeps an enhancement from turning into an obstacle. It holds for any animation, not just View Transitions.

A concrete example: from list to detail

The clearest case is moving from a grid of articles to an article page. On the grid, the thumbnail carries a transition name; on the detail page, the header image carries the same name. On click, the browser links the two and grows the thumbnail to its final position while the rest of the page fades. The user keeps the visual thread: they see where the content they are reading came from, which lowers the mental cost of a navigation.

For the effect to stay clean, the name must be present on only one element at a time in each view. If several thumbnails share the same name at the same instant, the browser no longer knows which one to animate and drops the transition. The practical rule is to build the name from a unique identifier, such as the article slug, rather than a fixed value reused everywhere.

Pitfalls to know

Three mistakes come up often. The first is the duplicated transition name, which silently cancels the animation. The second is layout shift: if the content reflows during capture, the snapshot freezes an intermediate state and the animation appears to jump. Better to reserve transitions for changes where the structure stays stable. The third is cost: each named element generates its own snapshots, and multiplying names on a single view weighs down rendering with no visible benefit. A few key elements are almost always enough.

One last habit avoids many disappointments: a transition must never mask a real loading time. If the next page is waiting on data, the animation plays over an incomplete screen and feels slow. The API dresses up a navigation that is already ready; it replaces neither a loading state nor a waiting indicator.

Tested with those habits, the API delivers: it makes an interface more legible without adding debt, and steps aside on its own where the browser does not yet follow.

Support status and adoption strategy

Same-document transitions reached Baseline status in October 2025 and work across the major browsers. Cross-document transitions are available in Chromium browsers and in recent Safari, while Firefox is still working on them. Because the API degrades cleanly, nothing prevents adopting it today as progressive enhancement.

FeatureChrome / EdgeSafariFirefox
Same-document transitions111+18+133+
Cross-document transitions126+18.2+in progress

Marker. The cross-document transition is limited to same-origin navigations and does not replace an app router: it dresses up a navigation that already exists. Treat it as a decorative layer, never as a functional dependency.

The takeaway

View Transitions covers two needs with a single grammar: animating a DOM update in a single-page app, and smoothing navigation between classic pages. The first variant is broadly available, the second is advancing fast. In both cases the API only improves what exists without breaking it, which makes it an ideal candidate for cautious adoption: wire it in where it adds clarity, cut it where motion gets in the way.

I have replaced several animation dependencies with this API on recent projects, and the result is clear: less JavaScript, a rendering closer to native, and predictable behaviour. My only guardrail is never to make a feature depend on the transition itself. I treat it as visual sugar, tested with reduced motion turned on, and I check that the page stays usable if the animation does not play. On those terms, it is one of the rare new features I enable in production without hesitation. — Simon Janvier

Further reading

Reference documentation, MDN Web Docs: developer.mozilla.org — View Transition API

Also on Mail Studio

Read next