React Router and TanStack Router sell you a promise: client-side navigation feels instant because the entire app lives in memory. The cost is brutal — SPA hydration, bundle overhead, route state management, and losing SEO hardness that static multi-page rendering gives you for free. Astro View Transitions flip the script: you get SPA-smooth page animations, persistent UI state across navigations, and keep every advantage of multi-page rendering (fast first load, zero hydration, clean SEO, per-page code splitting). The browser handles the animations; Astro handles the page swaps.
The Problem View Transitions Solve
A marketing site built with Astro pages renders fast and caches aggressively at the edge. But navigating between pages feels janky — the browser unloads the old page, loads the new one, the layout flashes white, elements reposition, JavaScript re-fires. Visitors expect SPA smoothness from modern web apps; clicking a link shouldn't feel like 2010. Enter <ViewTransitions />: drop one component into your Layout, add transition:name to persistent elements (header, footer, sidebar), and page swaps animate seamlessly. The header doesn't unmount; it transitions. The footer slides out softly. Background patterns cross-fade. All without client-side routing.
How View Transitions Work
Astro's View Transitions API wraps the browser's native View Transitions Web API. You add one line to your Layout:
{`import { ViewTransitions } from 'astro:transitions';
export default function Layout({ children }) {
return (
{children}
);
}`}
Now every navigation becomes a transition. The browser captures the current DOM, fetches the new page HTML, diffs it, and animates old elements out, new ones in. To keep elements alive across page swaps, add transition:name:
{`// Persistent header — won't unmount on nav
// New content animates in, old animates out
{children}
`}
Elements with the same transition:name on both pages don't unmount; they morph across the page swap. A meridian globe on the home page persists as you navigate to services — it stays rendered, position animates, SVG state (rotation, scale) carries over. No re-mount, no state loss.
Three Real Examples in Velocity X
1. Meridian globe persistence. Velocity X home page features a spinning WebGL globe in the hero. Clicking "Services" navigates to the services page, which also has the globe in a different position. The browser animates the globe's position, size, and rotation across the navigation — it never unmounts. GSAP animations keep running; the element just changes layout. Users perceive the app as one fluid experience, not a page reload.
2. Header and footer state. The header nav includes a dropdown menu and a theme toggle (dark/light). Navigate to a pricing page with ViewTransitions active — the header animates smoothly, the theme state persists (you're still in dark mode), the dropdown doesn't flicker closed. In an SPA, this is baked-in; in a multi-page site, it requires ViewTransitions to keep the header alive.
3. Scroll position and focus management. Click a blog post link from the home page. The page fetches new HTML, fades out the home hero, fades in the blog article. The browser automatically scrolls to top (you can customize this), and focus moves to the new page's main content region. All automatic; you don't wire up route state machines.
Lifecycle Hooks for Third-Party Libraries
View Transitions change when your JavaScript runs. The astro:page-load event fires after every page navigation (including the initial load). If you're initializing GSAP, Lenis smooth scroll, or analytics on page load, re-fire them in astro:page-load:
{`document.addEventListener('astro:page-load', () => {
// Re-init GSAP animations
gsap.registerPlugin(ScrollTrigger);
ScrollTrigger.refresh();
// Re-init smooth scroll
const lenis = new Lenis();
function raf(time) {
lenis.raf(time);
requestAnimationFrame(raf);
}
requestAnimationFrame(raf);
// Track page view
gtag('config', 'GA_ID', { page_path: window.location.pathname });
});`}
This fires after ViewTransitions completes the animation and the new page is interactive. No more "why isn't GSAP working on this page?" — it's because you didn't listen to astro:page-load.
ViewTransitions vs SPA Routing
React Router / TanStack Router: Client-side routing, single JavaScript bundle, entire app in memory, fast client-to-client navigation, slow first load (hydration cost), bundle bloat, SEO requires extra config, per-route code splitting is manual.
Astro ViewTransitions: Server-rendered multi-page, per-page JavaScript bundles, fast first load, zero hydration, clean SEO (static HTML), SPA-smooth animations, smaller client bundles, lifecycle hooks for per-page setup, works in older browsers (graceful fallback: normal page nav if transitions unsupported).
ViewTransitions aren't "faster" than SPA routing in absolute terms. But they're faster at first load (no hydration) and smaller at ongoing navigation (you're not shipping your entire app to the browser). Pick ViewTransitions when your site is predominantly server-rendered and you want SPA polish. Pick SPA routing when your app is heavily interactive (dashboard, editor, real-time collab).
Six FAQs
Do ViewTransitions work in all browsers?
Chrome, Edge, and Opera support them natively. Firefox support landed in 2024. Safari is coming in 2026. For unsupported browsers, Astro falls back to normal page navigation — no animation, but the site works. Check caniuse.com for current support.
Can I customize the animation timing and easing?
Yes. Use CSS @view-transition rules to control duration, easing, and which elements animate. You can make some elements fade, others slide, others instant.
What if an element has the same transition:name on every page?
It will persist and animate across all page swaps. That's the intended use case for headers, footers, sidebars — any chrome that lives on every page.
Do ViewTransitions hurt Largest Contentful Paint?
No. ViewTransitions fire after the page is loaded and interactive. They don't delay rendering; they animate after.
Can I disable ViewTransitions on specific links?
Yes. Add data-astro-transition="none" to a link to bypass the animation and force a full page reload.
What's the performance overhead?
Negligible. The View Transitions API is native browser tech. Astro's glue code is ~1kb. No bundle bloat, no JavaScript runtime cost.
The Bottom Line
View Transitions are Astro's answer to "I want an app-like experience without ditching static rendering." They give you SPA-smooth animations on a multi-page foundation — fast first load, clean SEO, per-page code splitting, graceful fallbacks. Your header persists, your footer animates, your page content crossfades, and the browser handles it all natively. If you're building a marketing site, content site, or docs site and want it to feel modern without the SPA tax, ViewTransitions is the move. For a deeper dive into Astro's static-dynamic hybrid, see our Server Islands guide. And to see ViewTransitions in action across a real product, check Velocity X pricing.