Page Exit

Animate elements before navigating away from the page.

.onPageExit() intercepts link clicks, plays the timeline to completion, and then navigates — the go-to trigger for page-out transitions, exit fades, and outgoing slide animations.

Basic Usage

Chain .onPageExit() after defining your animation. When a visitor clicks an eligible navigation link, the SDK plays the timeline and waits for it to finish before following the navigation.

typescript
import { Motion } from "@motion.page/sdk";

Motion("exit", "body", {
  to: { opacity: 0 },
  duration: 0.4,
  ease: "power2.in",
}).onPageExit();

Options

.onPageExit() accepts an optional config object:

Option Type Default Description
mode 'all' | 'include' | 'exclude' 'all' Which eligible links to intercept. 'all' catches every eligible <a> click; 'include' only fires on matched selectors; 'exclude' fires on all links except matched selectors.
selectors string CSS selector(s) for link filtering. Required when mode is 'include'; used as the exclusion list when mode is 'exclude'. Separate multiple selectors with a comma.
skipHref ('anchor' | 'javascript' | 'mailto')[] Href patterns to never intercept. 'anchor' skips #hash links; 'javascript' skips javascript: hrefs; 'mailto' skips mailto: and tel: links.

The trigger always leaves downloads, missing/empty hrefs, non-primary clicks, Ctrl/Cmd/Shift/Alt clicks, and links targeting a context other than _self to the browser. While an exit is already playing, the first eligible destination remains authoritative: another ordinary link click is canceled without restarting the timeline or replacing that URL.

Links added after .onPageExit() registration are supported automatically, including navigation rendered later by an SPA or CMS. Include/exclude selectors are evaluated against the clicked link and its current ancestor chain, so dynamically added containers and later class changes use the live DOM. Keyboard activation of an eligible link follows the same exit sequence as a pointer click.

An invalid selector never crashes navigation. In include mode it matches nothing; in exclude mode it excludes nothing and eligible links continue to use the exit animation. Fix invalid-selector warnings in development rather than relying on this fallback.


By default all eligible links trigger the exit animation. Pass skipHref to additionally bypass hash anchors, javascript: hrefs, and mailto links — a safe default for most sites.

typescript
Motion("exit", "body", {
  to: { opacity: 0 },
  duration: 0.4,
  ease: "power2.in",
}).onPageExit({ skipHref: ["anchor", "mailto"] });

To exclude specific links by class or selector, use mode: 'exclude' with a selectors list. Any <a> element (or a parent element) matching those selectors is skipped.

typescript
// Skip links inside the nav and any element with .no-exit
Motion("exit", "body", {
  to: { opacity: 0 },
  duration: 0.4,
  ease: "power2.in",
}).onPageExit({
  mode: "exclude",
  selectors: "nav a, .no-exit",
});

The selector format also supports parent-element targeting: #my-menu.no-animation will look up the ancestor chain of the clicked <a> and skip navigation if any parent has an ID of my-menu and a class of no-animation.


Use mode: 'include' with a selectors list to only intercept certain links — for example, navigation links or calls-to-action — leaving all other links unaffected.

typescript
// Only intercept main-nav and CTA links
Motion("exit", ".page-wrapper", {
  to: { opacity: 0, y: -20 },
  duration: 0.35,
  ease: "power2.in",
}).onPageExit({
  mode: "include",
  selectors: ".nav-link, .cta-button",
});

Fade-Out Exit

The simplest exit: fade the entire page to black before navigating.

typescript
Motion("fade-out", "body", {
  to: { opacity: 0 },
  duration: 0.5,
  ease: "power1.in",
}).onPageExit({ skipHref: ["anchor", "mailto"] });

Slide-Out Exit

Slide the page content upward while fading out — a classic page-transition feel.

typescript
Motion("slide-out", ".page-wrapper", {
  to: { opacity: 0, y: -40 },
  duration: 0.45,
  ease: "power2.in",
}).onPageExit({ skipHref: ["anchor", "mailto"] });


Pairing with Page Load

.onPageExit() and .onPageLoad() are natural complements. Combine them to build a full enter/leave transition: elements animate in when the page loads, and animate out when the visitor leaves.

typescript
import { Motion } from "@motion.page/sdk";

// Animate in on arrival
Motion("enter", ".page-wrapper", {
  from: { opacity: 0, y: 30 },
  duration: 0.6,
  ease: "power3.out",
}).onPageLoad();

// Animate out on departure
Motion("exit", ".page-wrapper", {
  to: { opacity: 0, y: -30 },
  duration: 0.4,
  ease: "power2.in",
}).onPageExit({ skipHref: ["anchor", "mailto"] });