patternjavascriptastroTip
Astro View Transitions for SPA-like page navigation
Viewed 0 times
Astro 3.0+ (View Transitions stable)
view transitionspage transitionsSPA navigationtransition:nametransition:persistastro:page-load
Problem
Multi-page Astro apps have full-page reloads between routes, losing the smooth navigation experience of SPAs. Adding a full SPA framework adds unnecessary JavaScript.
Solution
Add <ViewTransitions /> to the layout and name elements for persistent state:
// src/layouts/BaseLayout.astro
---
import { ViewTransitions } from 'astro:transitions';
---
<html>
<head>
<ViewTransitions />
</head>
<body>
<slot />
</body>
</html>
// Persist an element across page transitions
<nav transition:persist>
<!-- nav stays mounted between pages -->
</nav>
// Named transitions for matched elements
<img
src={post.cover}
transition:name={
/>
<!-- The image morphs between list and detail page -->
// Custom animation
<div transition:animate="slide">
Content slides in from the right
</div>
// Opt-out individual links
<a href="/external" data-astro-reload>Full reload</a>
// Lifecycle events
document.addEventListener('astro:page-load', () => {
// Runs after every navigation (like DOMContentLoaded for SPA)
initializePlugins();
});
// src/layouts/BaseLayout.astro
---
import { ViewTransitions } from 'astro:transitions';
---
<html>
<head>
<ViewTransitions />
</head>
<body>
<slot />
</body>
</html>
// Persist an element across page transitions
<nav transition:persist>
<!-- nav stays mounted between pages -->
</nav>
// Named transitions for matched elements
<img
src={post.cover}
transition:name={
cover-${post.slug}}/>
<!-- The image morphs between list and detail page -->
// Custom animation
<div transition:animate="slide">
Content slides in from the right
</div>
// Opt-out individual links
<a href="/external" data-astro-reload>Full reload</a>
// Lifecycle events
document.addEventListener('astro:page-load', () => {
// Runs after every navigation (like DOMContentLoaded for SPA)
initializePlugins();
});
Why
Astro View Transitions uses the browser's native View Transitions API with a JavaScript fallback. It intercepts clicks, fetches the new page, and morphs the DOM with CSS animations — no framework router needed. Pages remain fully server-rendered.
Gotchas
- transition:name must be unique on the page — duplicate names cause broken animations
- Scripts in <head> run once — use astro:page-load event for per-navigation scripts
- transition:persist keeps component state mounted — reinitialize if the component needs fresh state
- Native View Transitions API requires Chrome 111+ — fallback is an instant swap without animation
Code Snippets
View Transition lifecycle events
// Re-run scripts after navigation
document.addEventListener('astro:page-load', () => {
initCarousel();
setupAnalytics();
});
// Before navigation starts
document.addEventListener('astro:before-swap', (e) => {
saveScrollPosition();
});Context
When adding smooth page transitions to an Astro multi-page application
Revisions (0)
No revisions yet.