Have you ever installed all of Framer Motion into a React app just to get a page transition fade-in?
Or hand-written a pile of requestAnimationFrame logic for a multi-page site, managing your own snapshots and compositing, only to end up with something less natural than a native app?
In October 2025, the platform gave us the official answer.
View Transitions API officially joined Baseline Newly Available — same-document transitions are fully supported across Chrome 111+, Edge 111+, Firefox 133+, and Safari 18+. The browser natively handles snapshots, compositing, and animation. You just tell it "the DOM is about to change."
How It Works: Three-Phase Snapshot, Browser Handles Everything
View Transitions API has an elegant design. It breaks a transition into three phases:
- Snapshot old state — the browser takes a screenshot of the current page
- Execute DOM update — your callback runs, the DOM changes
- Snapshot new state → calculate diff → generate animation — the browser auto-interpolates
All of this happens within a single frame. Users never see a jarring switch — only a smooth transition.
The key insight: the browser handles snapshots and compositing; you only need to think about logic.
Minimum Implementation: One Line of Code
SPA (Single Page Application)
// Before
updateTheDOMSomehow();
// After
document.startViewTransition(() => updateTheDOMSomehow());
That's it. The default effect is a cross-fade. No CSS required.
MPA (Multi-Page Application)
/* Two lines of CSS for your entire site's page navigation */
@view-transition {
navigation: auto;
}
Add this to your global CSS and every <a> link navigation automatically gets a transition animation. Exceptionally high ROI.
Custom Animations: CSS Pseudo-Elements
Not happy with the default fade? During a transition, the browser exposes two CSS pseudo-elements:
/* Old state snapshot — slide out left */
::view-transition-old(root) {
animation: slide-out-left 0.3s ease-out;
}
/* New state — slide in from right */
::view-transition-new(root) {
animation: slide-in-right 0.3s ease-out;
}
@keyframes slide-out-left {
to { transform: translateX(-100%); }
}
@keyframes slide-in-right {
from { transform: translateX(100%); }
}
Control duration, easing, and animation effect through CSS — same as any regular CSS animation.
Named Transitions: Element-Level Morph Animation
This is View Transitions' most powerful capability — automatically morphing between same-named elements in different states.
Want "click a list thumbnail and it smoothly expands into the full detail image"?
/* List page thumbnail */
.thumbnail {
view-transition-name: product-image;
}
/* Detail page full-screen image */
.fullscreen-image {
view-transition-name: product-image;
}
The browser automatically calculates position and size differences between the two elements across pages/states, then generates interpolated animation. No manual coordinate calculation, no absolute positioning tricks.
Great for:
- List → detail page navigation (iOS-style card expansion)
- Image gallery fullscreen expand
- Shopping cart fly-in animation
- Data table row expansion
Comparison With Existing Solutions
| Solution | Bundle Size | Framework Dependency | MPA Support | Browser Support |
|---|---|---|---|---|
| Framer Motion | ~50KB | React | ❌ | All |
| React Spring | ~25KB | React | ❌ | All |
| GSAP | ~70KB | None | Manual | All |
| View Transitions API | 0KB | None | ✅ | Chrome/Edge/Safari/Firefox(SPA) |
Zero dependencies, zero bundle, native MPA support. For new projects with modest animation needs, View Transitions is the default choice.
Promise API: Precise Timing Control
const transition = document.startViewTransition(() => updateDOM());
// Wait for animation to start (pseudo-elements created, animation about to begin)
await transition.ready;
// Use Web Animations API here for further control
// Wait for animation to finish
await transition.finished;
// Do cleanup or next actions here
Useful for: chained animation orchestration, firing analytics events when animation completes, updating router state after transition.
Gotchas to Avoid
1. Snapshots are bitmaps, not live DOM
During animation, elements become screenshots (images). font-size animations and clip-path changes don't take effect during the animation. If you need font size transitions, trigger them after the animation ends.
2. Named elements must be unique on the page
Each view-transition-name can only be used by one element per page. List item Morph animations require dynamic name assignment (view-transition-name: item-${id}), set via JS on click:
item.style.viewTransitionName = `item-${item.dataset.id}`;
document.startViewTransition(() => navigateToDetail());
3. Cross-page morph requires consistent aspect ratios
If same-named elements have different aspect ratios across pages, the morph animation will warp. Text content is especially prone to line-wrapping issues — design with both endpoints' content dimensions in mind.
4. Firefox MPA support isn't there yet
Cross-document navigation (MPA page transitions) with View Transitions isn't supported in Firefox yet (expected in 2026). For Firefox-required MPA scenarios, use progressive enhancement with @supports:
@supports (view-transition-name: none) {
@view-transition {
navigation: auto;
}
}
5. Watch your INP metrics
If transition animations occupy the main thread too long, they'll affect INP (Interaction to Next Paint). Keep animations simple; avoid complex synchronous operations inside the startViewTransition callback.
Graceful Degradation: Non-Supporting Browsers Unaffected
View Transitions' most developer-friendly characteristic: in non-supporting browsers, the DOM updates normally — it just has no animation.
function showView(name) {
if (document.startViewTransition) {
document.startViewTransition(() => _doShowView(name));
} else {
_doShowView(name); // fallback: direct switch, no animation
}
}
Zero breakage, progressive enhancement, existing users unaffected.
Conclusion
View Transitions API is mature enough to be the default choice for new projects.
For SPAs, one startViewTransition call replaces mountains of Framer Motion boilerplate. For MPAs, two lines of CSS add transition effects to your entire site's navigation. For iOS-level card expansion, view-transition-name morph covers the use case.
Zero bundle size, no framework dependency, zero degradation risk. This API is underrated.
Sources: Trevor Lasn's View Transitions API Guide; Cyd Stumpel's Practical CSS View Transitions Guide; MDN Web Docs Baseline 2025
Top comments (0)