Implement CSS View Transitions API in Next.js App Router using next-view-transitions. Use when building page transitions, route animations, or the user mentions view transitions in a Next.js project.
How this skill is triggered — by the user, by Claude, or both
Slash command
/react-view-transitions:react-view-transitionsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
CSS View Transitions API for Next.js App Router. Package: `next-view-transitions` (by Shu Ding).
CSS View Transitions API for Next.js App Router. Package: next-view-transitions (by Shu Ding).
pnpm install next-view-transitions
<ViewTransitions>import { ViewTransitions } from 'next-view-transitions'
export default function Layout({ children }: { children: React.ReactNode }) {
return (
<ViewTransitions>
<html lang="en">
<body>{children}</body>
</html>
</ViewTransitions>
)
}
The <ViewTransitions> provider must wrap the <html> element. It handles:
<Link> for NavigationDrop-in replacement for next/link that triggers view transitions:
import { Link } from 'next-view-transitions'
export default function Nav() {
return <Link href="/about">Go to About</Link>
}
Accepts all the same props as next/link (href, as, replace, scroll, prefetch, etc.). Falls back to normal navigation if the browser doesn't support startViewTransition.
useTransitionRouter for Programmatic Navigation'use client'
import { useTransitionRouter } from 'next-view-transitions'
export default function Component() {
const router = useTransitionRouter()
return (
<button onClick={() => router.push('/about')}>
Go to About
</button>
)
}
Returns a TransitionRouter that extends Next.js AppRouterInstance with transition-aware push and replace.
<ViewTransitions>| Prop | Type | Description |
|---|---|---|
children | React.ReactNode | Must wrap the root <html> element |
<Link>Same props as next/link (React.ComponentProps<typeof NextLink>). Intercepts clicks to trigger document.startViewTransition() before navigating. Respects modifier keys (ctrl/cmd+click opens in new tab as usual).
useTransitionRouter()Returns TransitionRouter:
type TransitionOptions = {
onTransitionReady?: () => void
}
type TransitionRouter = AppRouterInstance & {
push: (href: string, options?: NavigateOptions & TransitionOptions) => void
replace: (href: string, options?: NavigateOptions & TransitionOptions) => void
}
router.push(href, options?) — navigate with view transitionrouter.replace(href, options?) — replace with view transitionrouter.back(), router.forward(), router.refresh(), router.prefetch() — inherited from Next.js routeronTransitionReady — callback fired when the transition's ready promise resolves (useful for custom animations via the Web Animations API)Use CSS to control transition animations. The browser creates ::view-transition-* pseudo-elements:
/* Default crossfade (works out of the box) */
::view-transition-old(root),
::view-transition-new(root) {
animation-duration: 0.3s;
}
/* Named transitions for specific elements */
.hero-image {
view-transition-name: hero;
}
::view-transition-old(hero),
::view-transition-new(hero) {
animation-duration: 0.5s;
animation-timing-function: ease-in-out;
}
/* Slide transition example */
@keyframes slide-from-right {
from { transform: translateX(100%); }
}
@keyframes slide-to-left {
to { transform: translateX(-100%); }
}
::view-transition-old(root) {
animation: 0.3s slide-to-left;
}
::view-transition-new(root) {
animation: 0.3s slide-from-right;
}
onTransitionReadyUse the Web Animations API for JS-driven transitions:
router.push('/next-page', {
onTransitionReady: () => {
document.documentElement.animate(
[
{ opacity: 1, transform: 'scale(1)' },
{ opacity: 0, transform: 'scale(0.95)' },
],
{
duration: 300,
easing: 'ease-in',
pseudoElement: '::view-transition-old(root)',
},
)
document.documentElement.animate(
[
{ opacity: 0, transform: 'scale(1.05)' },
{ opacity: 1, transform: 'scale(1)' },
],
{
duration: 300,
easing: 'ease-out',
pseudoElement: '::view-transition-new(root)',
},
)
},
})
'use client' — they run in the browser onlyview-transition-name values must be unique on the page at transition time — duplicates cause the transition to skip.Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub mikesilvis/ai-skills --plugin react-view-transitions