This document describes the View Transitions system in Astro, enabling client-side routing with smooth and accessible transitions between pages. The system intercepts navigation events such as link clicks and form submissions, loads new page content fetches, and performs DOM updates without full page reloads, creating an SPA-like experience that leverages server-rendered HTML. It supports both the native browser View Transitions API and a fallback mode simulating transitions using CSS animations.
The page elaborates on key components such as the router implementation in router.ts, DOM swapping mechanisms in swap-functions.ts, view transition modes, lifecycle events in events.ts, and the persistence system used to maintain elements across navigations.
For related systems see:
The View Transitions system centers around a client-side router implemented in router.ts, event-driven lifecycle management in events.ts, DOM update utilities in swap-functions.ts, and server-side transition CSS generation in transition.ts. It integrates a CSS-based animation fallback and also utilizes the native View Transition API when available.
Title: View Transitions Architecture
Sources: packages/astro/src/transitions/router.ts1-734 packages/astro/src/transitions/events.ts1-205 packages/astro/src/transitions/swap-functions.ts1-234 packages/astro/src/runtime/server/transition.ts1-266
The router maintains internal global state variables to track ongoing navigation and transitions:
| Variable | Type | Role | Location |
|---|---|---|---|
mostRecentNavigation | Navigation | undefined | Tracks the most recent navigation, contains an AbortController for cancellation | packages/astro/src/transitions/router.ts34 |
mostRecentTransition | Transition | undefined | Tracks the current transition state and the native ViewTransition object | packages/astro/src/transitions/router.ts36 |
originalLocation | URL | Stores the location prior to history traversal (popstate navigation) | packages/astro/src/transitions/router.ts39 |
currentHistoryIndex | number | Tracks the index in the browser history stack to determine direction | packages/astro/src/transitions/router.ts70 |
Sources: packages/astro/src/transitions/router.ts34-40 packages/astro/src/transitions/router.ts70
The navigation process composes several asynchronous steps:
navigate() call).AbortController.astro:before-preparation event.fetchHTML().astro:after-preparation.document.startViewTransition() is used or the fallback simulation transition starts.astro:before-swap event is dispatched before performing DOM swapping.head and body elements.astro:after-swap event is fired.astro:page-load.Title: Navigation Lifecycle Sequence
Sources: packages/astro/src/transitions/router.ts340-575 packages/astro/src/transitions/events.ts147-204
The View Transitions system introduces custom DOM events defined in events.ts:
| Event Name | Event Class | Cancelable | Description |
|---|---|---|---|
astro:before-preparation | TransitionBeforePreparationEvent | Yes | Fired before fetching new content. Allows replacing the loader. |
astro:after-preparation | Event | No | Fired after the new page content is loaded and parsed. |
astro:before-swap | TransitionBeforeSwapEvent | No | Fired before DOM swapping. Provides access to the swap() function. |
astro:after-swap | Event | No | Fired after the DOM swap completes. |
astro:page-load | Event | No | Fired after scripts are run and page is fully loaded. |
Sources: packages/astro/src/transitions/events.ts11-127
The actual DOM update replaces the document's head and body with the new content. The swap process preserves elements marked with data-astro-transition-persist.
Title: DOM Swap Logic Flow
deselectScripts() disables re-execution of scripts that already ran unless they have data-astro-rerun. packages/astro/src/transitions/swap-functions.ts26-39swapRootAttributes() synchronizes <html> attributes, preserving NON_OVERRIDABLE_ASTRO_ATTRS. packages/astro/src/transitions/swap-functions.ts47-55swapHeadElements() replaces the <head> content, preserving server island markers. packages/astro/src/transitions/swap-functions.ts60-100swapBodyElement() replaces the <body>, ensuring persisted elements survive by lifting them temporarily to the documentElement. packages/astro/src/transitions/swap-functions.ts102-152attachShadowRoots() polyfills Declarative Shadow DOM for templates with shadowrootmode. packages/astro/src/transitions/swap-functions.ts160-176Sources: packages/astro/src/transitions/swap-functions.ts24-161 packages/astro/src/transitions/swap-functions.ts102-152
Elements that carry the data-astro-transition-persist attribute are preserved to avoid state loss (e.g., video players, input state).
moveBefore() DOM API for zero-detachment atomic moves when available (Chrome 133+), preventing Safari from losing WebGL context on <canvas>. packages/astro/src/transitions/swap-functions.ts102-114<astro-island> elements: if props change, the ssr attribute is reset to allow re-rendering. packages/astro/src/transitions/swap-functions.ts139-147Sources: packages/astro/src/transitions/swap-functions.ts87-148
The server-side function renderTransition() generates CSS styles scoped to the transition name:
createTransitionScope() generates a unique scope ID (e.g., astro-hash-1). packages/astro/src/runtime/server/transition.ts22-25ViewTransitionStyleSheet creates the CSS rules for both modern ::view-transition-* pseudo-elements and fallback simulation selectors. packages/astro/src/runtime/server/transition.ts118-187reEncode() ensures transition names are safe for CSS identifiers, handling special characters and digits. packages/astro/src/runtime/server/transition.ts60-86Sources: packages/astro/src/runtime/server/transition.ts22-187
Astro provides predefined transition animations in index.ts:
fade(): Simple opacity transition with EASE_IN_OUT_QUART. packages/astro/src/transitions/index.ts52-76slide(): Directional slide (left/right) combined with fading. packages/astro/src/transitions/index.ts8-50Sources: packages/astro/src/transitions/index.ts8-77
The fetchHTML() function retrieves new page content:
internalFetchHeaders from the adapter configuration. packages/astro/src/transitions/router.ts93-96content-type to ensure only text/html or application/xhtml+xml are processed. packages/astro/src/transitions/router.ts98-105Sources: packages/astro/src/transitions/router.ts87-116
The router maintains accessibility compliance by announcing page changes:
announce() creates an aria-live="assertive" element. packages/astro/src/transitions/router.ts41-46h1 and updates the announcer after a 60ms delay. packages/astro/src/transitions/router.ts47-56Sources: packages/astro/src/transitions/router.ts41-57
Astro's View Transitions system provides a seamless SPA-like UX with progressive enhancement. It balances native browser APIs and fallback simulations with a persistence mechanism, accessibility support, and an extensible lifecycle event model. It integrates tightly with Astro's SSR environment to handle route changes and transition styling.
Refresh this wiki
This wiki was recently refreshed. Please wait 6 days to refresh again.