page-transition-choreography
Page Transition Choreography
When to use this
- Building smooth transitions between routes in an SPA or MPA.
- Coordinating exit animations (current page) with enter animations (next page).
- Preserving visual continuity of shared elements across pages (hero images, headers).
- Handling scroll position restoration during animated transitions.
- Do NOT use this for Barba.js-specific implementation; see
barba-spa-transitionsinstead.
Mental model
A page transition has four phases: trigger, exit, swap, enter. The trigger is usually a link click or programmatic navigation. Exit is the current page animating out. Swap is the DOM replacement (React re-render, Astro page swap, full HTML replace). Enter is the new page animating in.
The key design decision is overlap vs sequence. In a sequence model, exit completes fully before swap and enter begin. The user sees the old page leave, a brief empty/loading state, then the new page arrive. In an overlap model, the new page content is pre-fetched and both pages exist in the DOM simultaneously; the old page exits while the new page enters. Overlap looks smoother but is harder to implement because both pages need to coexist without layout conflicts (typically position: fixed with inset: 0 on both during the transition).
Scroll restoration is the hidden complexity. The browser's default behavior (scroll to top on navigation, restore on back/forward) fights animated transitions. You must take manual control: prevent default scroll on forward navigation, let the transition complete, then scroll to 0. On back/forward, capture the scroll position before exit, restore it after enter. The View Transitions API handles some of this natively.
Element continuity (a.k.a. shared element transitions) is the highest-impact technique. An image on page A appears to fly to its new position on page B. Under the hood, you snapshot the element's rect on both pages, calculate the delta, and FLIP animate it. The View Transitions API gives you view-transition-name for this, or you can implement it manually with the FLIP technique.