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-contentMain content area (auto-applied to <main>)
data-vt="header"page-headerSite header — persists across pages
data-vt="nav"site-navPrimary navigation
data-vt="sidebar"page-sidebarSidebar navigation — stays in place within sections
data-vt="hero"page-heroHero image or banner
data-vt="footer"site-footerSite 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.

Shared Element Morphing

For unique per-element names (galleries, product cards, lists), use data-vt-name:

The init script (view-transition-init.js) sets view-transition-name from the attribute value. This replaces the need for inline style attributes.

How the Init Script Works

  1. On DOMContentLoaded, discovers all [data-vt-name] elements
  2. Sets el.style.viewTransitionName from the attribute value
  3. Marks each element with data-vt-name-init to prevent double-processing
  4. A MutationObserver handles dynamically added elements

Tokens

Custom properties control transition duration:

Token Default Use Case
--view-transition-duration0.3sStandard transitions
--view-transition-duration-fast0.15sSubtle, quick transitions
--view-transition-duration-slow0.5sDramatic, 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 / Edge111+126+
Safari18+18+
FirefoxPendingPending

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: reduce is active (animation duration set to 0.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-name must 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.