design hubs
On this page
Patterns
3 min read

Page Transitions

Page transitions maintain spatial context as users navigate between routes — without them, every navigation feels like a hard cut that must be reoriented from scratch.

Without a page transition, navigating between routes is a hard cut — the current page disappears and a new one appears. Users must reorient entirely each time. A transition maintains continuity: the new page arrives from somewhere, and the user retains a spatial model of the interface.

The purpose of page transitions

Page transitions do two things. They communicate spatial direction — a new page sliding in from the right implies the user moved forward in a hierarchy; sliding in from the left implies moving back. And they provide a moment for the next page’s content to begin loading, reducing the jarring experience of content popping in after a blank flash.

Push and pop

The most common page transition pattern mirrors a navigation stack. Moving deeper into a hierarchy: the new page pushes in from the right while the current page slides to the left. Moving back: the current page slides off to the right as the previous page slides in from the left. This mirrors the physical metaphor of a card stack — forward is right, back is left. Consistency is essential: once users learn this pattern, they use it to build their spatial model.

Cross-fade

A simple cross-fade — the current page fading out as the new page fades in — communicates transition without implying direction. It is appropriate for non-hierarchical navigation where the pages are peers rather than parent/child — switching between top-level tabs, for example. At 150–200ms, a cross-fade is barely perceptible as a transition but eliminates the visual snap of a hard cut.

Shared element transitions and the View Transitions API

A shared element transition identifies an element that exists on both the current page and the destination page — a product image, a profile photo, a card — and animates it to its new position and size during the transition. The result is a powerful sense of spatial continuity: the user sees the same object move from the list to the detail view.

The View Transitions API provides a native browser mechanism with no library required. For same-document transitions (SPA routing):

document.startViewTransition(() => {
  updatePage(); // Update the DOM to the new state
});

Mark the shared element with a view-transition-name:

.product-image { view-transition-name: product-hero; }

The browser captures snapshots of the before/after state and animates the named element to its new position automatically. For multi-page navigation (standard HTML pages), the @view-transition CSS rule enables the API across full page loads — no JavaScript needed:

@view-transition { navigation: auto; }

The View Transitions API is now supported in all major browsers. It handles the cross-fade by default; shared element animations require the view-transition-name pairing. Disable it under prefers-reduced-motion:

@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*),
  ::view-transition-image-pair(*) { animation: none; }
}

Performance considerations

Page transitions involve animating entire page compositions. Use opacity and transform on page-level containers — never animate layout properties across a full page. Keep transition duration under 300ms for push/pop and under 200ms for cross-fade. Any longer and navigation feels sluggish.

The takeaway

Implement a consistent push/pop transition for hierarchical navigation and a cross-fade for peer navigation. Keep durations short. Use shared element transitions where a single element links the two pages contextually. Ensure transitions are disabled under prefers-reduced-motion.

Practice

0 / 3

Keyboard shortcuts

Show shortcuts
?
Search
CtrlK
Previous article
Next article
Close
Esc