Page transitions

Page transitions

The site's real navigation motion, live and tunable — with the network and server conditions a visitor actually brings. Throttle the fetch, feel the dead time, tune the timing variables, copy them back.

How this page works

  • Every run in the frame goes through the production DirectionalTransition and the recipes in view-transition.css — the GUI live-overrides only the :root timing variables, and clears them when you leave.
  • The network and server sliders insert the real dead time a navigation spends before anything moves: Next.js fetches the RSC payload, then the transition plays. Production ships no loading UI, so that stillness is the actual experience — the timeline below the frame plots it.
  • A view transition freezes the whole document while it runs (browser behavior), this GUI included. That is also true in production.
  • The frame scrolls through its own Lenis instance, tuned like the site's, and transition snapshots are clipped to the window while you are here — nothing escapes the mock browser.
  • Copy writes the :root block for view-transition.css.

Where each technique fires in production

nav-forward
Slide left + fade, going deeper. Card title links (components/Card) and pagination toward higher pages.
nav-back
Slide right + fade, going shallower. Pagination toward lower pages and back links.
nav-lateral
Pure fade, no spatial depth. The CMSLink default — header logo, takeover menu links, 404.
shared-element morph
A post card image and its detail hero carry the same view-transition-name (postImageVtName), so the browser interpolates between them over the move duration.
home-hero recede
The home hero is its own group (.vt-home-hero) and dollies back over 560ms, overlapping the incoming page.
pinned chrome
site-header, site-footer and the global WebGL canvas are named groups with animation: none — they hold rock-steady through every swap.
untagged — hard cut
Browser back/forward, revalidations, and card body clicks (the useClickableCard gap) carry no type, and default: 'none' keeps them silent by design.