Native motion in Next.js 15: View Transitions API in production in 2026
Six months of View Transitions in production. Where it replaces Framer Motion, where it breaks hydration, and how we rolled it across 11 projects without regressions.
Creastra Digest
- View Transitions shed 70–120 KB of JS per page versus Framer Motion
- Works on top of Next 15 useRouter without Suspense gymnastics
- Safari < 18.2 — fall back to no animation; do not try to polyfill
By early 2026 View Transitions are supported across all major browsers (Chrome 111+, Edge, Safari 18.2+, Firefox 130+ behind a flag). We rolled it into 11 projects over the past six months — the first time in five years that a native API beat the popular library on all three metrics that matter: weight, smoothness, and time-to-interactive.
What we replace
- Page-to-page transitions — previously Framer Motion + AnimatePresence
- Shared-element transitions (card → detail) — now via view-transition-name
- List-entry micro-animations — CSS animation on ::view-transition-new
- Chrome animation on sort change — same API, no extra re-renders
Minimal App Router example
// app/_components/Link.tsx — wrapper around next/link
'use client';
import { useRouter } from 'next/navigation';
import NextLink from 'next/link';
export function Link(props: React.ComponentProps<typeof NextLink>) {
const router = useRouter();
return (
<NextLink
{...props}
onClick={(e) => {
if (!('startViewTransition' in document)) return;
e.preventDefault();
document.startViewTransition(() => {
router.push(props.href.toString());
});
}}
/>
);
}Shared elements in two CSS rules
A product card in the catalogue and the same product on the detail page get the same view-transition-name. The browser morphs size, position, and corner radius automatically. We shipped this for the Grayn sports-nutrition catalogue — click-through to product detail rose 11.4% without an A/B test, because the transition creates an «app-like» feel and lowers click anxiety.
What breaks
- Hydration breaks if you trigger a Suspense boundary with loading inside the transition callback
- Framer Motion and View Transitions conflict — pick one per page
- iOS Safari < 18.2: the transition simply disappears (that is fine), but do not rely on `onfinish` without a feature check
- Long animations (>400 ms) wreck Core Web Vitals — INP turns red
- Images without explicit aspect-ratio jump during the morph
When not to bother
If you have an SPA with heavy client logic and already use Motion, migration eats 2–3 sprints without obvious upside. View Transitions shine where there were no animations at all — corporate sites, landings, catalogues. On complex dashboards the gain is dubious.
Measurements
Across 11 projects post-rollout: average page JS bundle −83 KB, INP improved from 248 ms to 174 ms, LCP unchanged, CLS down by 0.04. On the Par Khorosh franchise landing, Lighthouse Performance climbed from 78 to 94.