view-transitions
CSS-only page transition effects with named groups, shared element morphing, animation presets, and a declarative init script.
Quick Start
Import the opt-in CSS utility. This single import gives you smooth crossfade transitions on all same-origin navigations:
That’s it for basic crossfade. The <main> element automatically gets a named transition group (main-content) so content fades smoothly between pages.
For shared element morphing, add data-vt-name to elements that should animate between pages:
The data-vt-name attribute requires the init script (included in all doc site layouts, or import view-transition-init.js).
Named Groups
Use data-vt to assign common transition names to page regions. Named elements persist or morph across navigations instead of crossfading.
| Attribute | Transition Name | Use Case |
|---|---|---|
data-vt="main" | main-content | Main content area (auto-applied to <main>) |
data-vt="header" | page-header | Site header — persists across pages |
data-vt="nav" | site-nav | Primary navigation |
data-vt="sidebar" | page-sidebar | Sidebar navigation — stays in place within sections |
data-vt="hero" | page-hero | Hero image or banner |
data-vt="footer" | site-footer | Site footer |
When navigating between pages with the same named group, the browser morphs the element in place rather than crossfading. This keeps headers, sidebars, and footers visually stable during navigation.
Animation Presets
Apply animation presets to transition groups using data-vt-class. This uses the CSS view-transition-class property to style transitions without targeting individual names.
| Value | Effect |
|---|---|
slide-left | Old content slides out left, new slides in from right |
slide-right | Old content slides out right, new slides in from left |
scale | Old content scales down and fades, new scales up |
fade | Pure opacity crossfade (no morphing) |
none | Instant swap with no animation |
Tokens
Custom properties control transition duration:
| Token | Default | Use Case |
|---|---|---|
--view-transition-duration | 0.3s | Standard transitions |
--view-transition-duration-fast | 0.15s | Subtle, quick transitions |
--view-transition-duration-slow | 0.5s | Dramatic, deliberate transitions |
Demos
Interactive examples showing view transitions in action. Open in a new tab for the full MPA navigation experience.
Gallery Morph
Card grid with shared element morphing to detail pages.
List → Detail
Vertical list with title and thumbnail morphing to a detail view.
Nav Persistence
Header and sidebar stay in place while main content transitions.
Animation Presets
Side-by-side comparison of slide, scale, fade, and none presets.
MPA vs SPA
Multi-Page Applications (MPA)
For traditional multi-page sites, use the CSS @view-transition rule. This is what the Vanilla Breeze utility provides:
The browser automatically triggers transitions on same-origin navigations. No JavaScript needed.
Single-Page Applications (SPA)
For SPA routing (client-side navigation), use the JavaScript API:
The same CSS transition names and animation presets work with both approaches.
Browser Support
| Browser | Same-document | Cross-document (MPA) |
|---|---|---|
| Chrome / Edge | 111+ | 126+ |
| Safari | 18+ | 18+ |
| Firefox | Pending | Pending |
In unsupported browsers, pages load normally without transitions. No errors, no broken functionality — true progressive enhancement.
Accessibility
- Reduced motion: All transitions are disabled when
prefers-reduced-motion: reduceis active (animation duration set to0.01ms) - No content loss: View transitions are purely visual — content is always accessible regardless of browser support
- Focus management: The browser handles focus during cross-document navigations
- Performance: Transitions run on the compositor thread and don’t block the main thread
Best Practices
- Unique names per page: Each
view-transition-namemust be unique. Duplicate names on the same page cause the transition to fail silently. - Name sparingly: Only name elements that should morph or persist. Unnamed elements participate in the default crossfade, which is usually fine.
- Matching structure: Named elements on the source and destination pages should have similar visual size and position for the smoothest morph.
- Test both directions: Transitions should look good navigating both forward and back.
- Keep durations short: 200–400ms feels responsive. Longer durations can feel sluggish.
- Avoid naming lists: Don’t give the same transition name to multiple list items. Name only the specific item being navigated to.