Your marketing site is a multi-page app (MPA). Each page is static HTML. Navigation is a full page reload. The browser clears the DOM, fetches new HTML, re-renders from scratch. On a fast connection it's fine. On 4G it feels sluggish. There's a moment of whitespace, a brief delay, the sense that the site is "clunky." Then SPA routing came along — React Router, Next.js dynamic routes, Remix — and solved the problem with client-side navigation. But they solved it by shipping 250kb of JavaScript. Astro's View Transitions split the difference: MPA architecture with SPA feel for 4 lines of code and zero JavaScript overhead. This is the move that makes Velocity X feel buttery smooth.
View Transitions is a browser API (CSS Transitions API, still being standardized) that lets you animate between page states. Astro wraps it in a tiny library that hooks into its routing. You drop <ViewTransitions /> into your layout. Every navigation animates. Links don't reload — the page fades out, new content fades in, scroll resets, and the illusion is perfect. It's not a real SPA. It IS a real SPA user experience. The kicker: the performance is better than a real SPA because you're not shipping a router or state manager. This is how you win.
What View Transitions Actually Are
The CSS Transitions API lets you define transitions between the "old page" and the "new page." Normally, navigation is synchronous: browser stops rendering, fetches new HTML, clears the DOM, renders. User sees a flash. With View Transitions, you can animate the swap. The old page fades out over 400ms. While it's fading, the new page is being fetched and parsed in the background. As the fade completes, the new page fades in. To the user, it looks like navigation is instant and smooth. There's no "flash." There's no wait. Just continuous motion.
Astro's implementation is elegant: it wraps the native API and handles all the plumbing. You don't touch CSS. You don't manage transitions manually. You just add one component to your layout, and every page navigation gets an automatic fade/slide/zoom effect. The library intercepts link clicks, starts the transition, fetches the new page, swaps the DOM, and triggers the new page's animations. All synchronous, all seamless, all from 4 lines of code.
Why MPA + Transitions Beats SPA for 95% of Sites
A single-page app (SPA) like Next.js or React Router owns all of navigation. Links are intercepted by JavaScript. The router fetches JSON (or JSX), updates client-side state, re-renders the page. No full reload. Navigation is instant. But you paid for it: you shipped 250kb of React, 30kb of Router, state management, hydration delays, and a build toolchain.
An MPA with View Transitions is structurally the same: links are intercepted (by Astro's tiny transition library, not a full router), the server sends HTML, the page re-renders. But you paid almost nothing: Astro's View Transitions is ~2kb. The site is static. No build overhead. No hydration. No runtime state management. The page load is still as fast as a static site. The feel is as smooth as an SPA.
The math: SPA overhead = 250kb+ JavaScript + build complexity. View Transitions overhead = 2kb + one component. Same user experience. Vastly different cost. For 95% of websites (marketing sites, blogs, documentation, portfolios), this is the obvious choice. Your site doesn't need a router. It doesn't need state. It needs fast page loads and smooth transitions. View Transitions gives you both.
The 4-Line Implementation
Step 1: Install and import.
npm install astro @astrojs/view-transitions
Step 2: Add to your layout.
// src/layouts/Layout.astro
---
import { ViewTransitions } from 'astro:transitions';
---
<html lang="en">
<head>
<ViewTransitions />
</head>
<body>
<slot />
</body>
</html>
That's it. Every page now has smooth transitions on navigation. Links fade out, new content fades in, and the site feels like an SPA without shipping SPA code. Click a link. Watch the magic. The transition is built-in and automatic.
Step 3 (optional): Customize the animation.
<ViewTransitions fallback="swap" />
The fallback prop controls what happens on unsupported browsers. swap means instant navigation (no animation, just a normal MPA reload). You can also customize the animation with CSS by targeting the ::view-transition-old(root) and ::view-transition-new(root) pseudo-elements. Astro provides sensible defaults. For 95% of sites, you don't touch this.
What Actually Breaks (And How to Fix It)
Problem 1: Scripts re-run on every page transition.
The DOM is re-rendered during navigation. Any <script> tags in your page re-execute. If you have a script that initializes a plugin (like a lightbox or slider), it runs twice on the second navigation. This causes duplicate event listeners, memory leaks, and weird behavior.
Fix: Use Astro's transition:persist.
<script is:inline transition:persist>
// This script runs once and persists across page changes
console.log('Lightbox initialized');
</script>
The transition:persist attribute tells Astro to keep the script element in the DOM across page transitions instead of re-running it. Your plugin initializes once. Navigation is smooth. Done.
Problem 2: Scroll position doesn't reset.
When you navigate to a new page, the scroll position should snap to the top. With View Transitions, if the new page is taller than the old page, scroll position might stay mid-page. Users land on the page but can't see the top.
Fix: Reset scroll on every transition.
// src/lib/viewTransitionsHooks.ts
document.addEventListener('astro:after-swap', () => {
window.scrollTo(0, 0);
});
// Add to your layout
import { viewTransitionsHooks } from 'astro:transitions/client';
The astro:after-swap event fires after the DOM has been swapped. Reset scroll to top. Problem solved.
Problem 3: Theme flash on dark-mode sites.
If you use CSS to toggle between light and dark theme (controlled by a class on <html> or a CSS variable), the old page's theme renders briefly before the new page's theme kicks in. Flash. Annoying.
Fix: Apply theme before the transition completes.
// In your theme toggle script
document.addEventListener('astro:before-preparation', (e) => {
const isDark = localStorage.getItem('theme') === 'dark';
if (isDark) document.documentElement.classList.add('dark');
});
document.addEventListener('astro:after-swap', (e) => {
// Re-apply theme after swap to catch any CSS changes
const isDark = localStorage.getItem('theme') === 'dark';
if (isDark) document.documentElement.classList.add('dark');
});
Astro fires astro:before-preparation before fetching the new page. Apply your theme there. Then re-apply on astro:after-swap to catch any CSS cascading. No flash.
Customizing the Animation
The default fade animation is solid. But you can do more. CSS ::view-transition-old() and ::view-transition-new() pseudo-elements let you define custom animations.
// In your Layout CSS or Global CSS
@view-transition {
navigation: auto;
}
::view-transition-old(root) {
animation: slide-out-left 0.4s ease-in-out;
}
::view-transition-new(root) {
animation: slide-in-right 0.4s ease-in-out;
}
@keyframes slide-out-left {
from { transform: translateX(0); opacity: 1; }
to { transform: translateX(-100%); opacity: 0; }
}
@keyframes slide-in-right {
from { transform: translateX(100%); opacity: 0; }
to { transform: translateX(0); opacity: 1; }
}
Now navigation slides left (old page) and right (new page) instead of fading. You can do zoom, rotate, blur, anything CSS Transitions support. Astro provides the hooks. You define the motion. This is why Velocity X feels premium — transitions are carefully tuned, not defaulted.
Browser Support and Fallback
View Transitions is supported in Chrome 111+, Edge 111+, Opera 97+. Safari is coming (probably 2026-2027). Firefox is "under consideration." For unsupported browsers, Astro falls back to instant navigation (normal MPA reload). No animation, but the site still works. Users don't notice. The experience degrades gracefully.
You can detect support and customize behavior:
if (document.startViewTransition) {
// Transitions are supported
} else {
// Fallback to instant navigation
}
Six FAQs
Isn't this the same as a SPA?
User experience-wise, yes. Architecturally, no. View Transitions is just an animation layer on top of MPA navigation. The site is still static HTML. No client-side router. No state management. No hydration. You get SPA feel with MPA simplicity.
Do I need React for View Transitions?
No. View Transitions works in pure Astro (static HTML + Astro components). If you're using React islands, they work fine with View Transitions — the transition wraps the entire page, islands included.
Does View Transitions hurt SEO?
No. The site is still fully server-rendered. Every page is static HTML. Search engines crawl it normally. View Transitions is purely a client-side animation detail.
Can I animate specific page sections during transitions?
Yes. Use the transition:name directive on elements to animate them independently across page swaps. A header could slide left while the footer slides right. Full docs in Astro's transitions guide.
What's the performance cost?
Negligible. The Astro View Transitions library is ~2kb. The animation itself uses native CSS Transitions (hardware-accelerated). The DOM swap is the same cost as a normal MPA navigation. You're not adding meaningful overhead.
Should I use View Transitions on every site?
If it's a marketing site, blog, docs, or portfolio: yes. If it's an app (dashboard, editor, collaborative tool): probably not — you're likely already on React or Next.js. If you're on Astro, View Transitions is essentially free. Add it.
The Bottom Line
View Transitions gives you SPA feel (smooth navigation, no flash, premium feel) for MPA cost (static HTML, tiny library, zero complexity). It's the closest thing to a free lunch in web development. Add one component to your layout. Every navigation animates. Your site feels 10× faster because the motion is smooth, even if the actual page load time is identical.
This is especially true for Astro sites and Velocity X builds. The architectural simplicity of static HTML + View Transitions beats the complexity of a real SPA in almost every way: faster builds, better SEO, simpler code, zero hydration overhead, and a user experience that's just as smooth. If you're building a marketing site in 2026 and you're not using View Transitions, you're leaving performance and feel on the table.
Ready to ship a site with that SPA smoothness? Check out Aidxn Design web projects to discuss your next build, or dive deeper into why Astro 5 is the framework to learn in 2026.