Performance Optimization for View Transitions

Avoid jank, reduce snapshot memory, and combine the View Transitions API with the Web Animations API for fine-tuned, 60fps transitions on mid-range mobile.

Integration

Detailed Explanation

The Cost Model

Each View Transition costs:

  1. Two raster snapshots of the affected viewport — proportional to viewport size and device-pixel-ratio.
  2. One compositor layer per named element — 10 named elements = 10 extra layers.
  3. Animation interpolation — typically GPU-accelerated, so cheap once layers exist.

Snapshot capture is the dominant cost. On a 4K device with 50 named elements, the capture phase can take 50–80ms — long enough to cause a visible delay before the animation starts.

Reduce named elements

Only name elements that need shared-element morphing. If a list item just needs to cross-fade with the rest of the page, leave it unnamed and it joins the root group for free.

Use will-change strategically

.expensive-card {
  view-transition-name: card;
  will-change: transform, opacity;
}

will-change promotes the element to its own compositor layer before the transition starts, so the browser does not need to allocate a layer mid-snapshot. Remove it after the transition finishes:

const t = document.startViewTransition(update);
await t.finished;
document.querySelectorAll('.expensive-card').forEach(el => el.style.willChange = 'auto');

Pause animations during transitions

If your page has running CSS animations (rotating loaders, marquees), pause them during the transition to free up paint cycles:

:root:has(::view-transition) * {
  animation-play-state: paused !important;
}

Use the Web Animations API for fine control

The pseudo-elements accept WAAPI animations:

const t = document.startViewTransition(update);
await t.ready;
document.documentElement.animate(
  { opacity: [0, 1] },
  {
    duration: 300,
    easing: 'cubic-bezier(0.4, 0, 0.2, 1)',
    pseudoElement: '::view-transition-new(root)',
  },
);

WAAPI animations override CSS @keyframes for the same pseudo-element, so you can authoritatively control the animation from JS when you need dynamic durations or callbacks.

Profiling

Open Chrome DevTools → Performance → record a transition. The "ViewTransition" event in the timeline shows snapshot capture time, layer count, and animation duration. If snapshot capture exceeds 16ms, reduce viewport size or named element count.

Use Case

Production sites targeting mid-range Android (e.g., $200 phones with 4GB RAM) where every millisecond matters. Also useful for transition-heavy applications like image editors or game lobbies where multiple transitions may occur in rapid succession.

Try ItView Transitions API Generator

Open full tool