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 any <a> 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:

OptionTypeDefaultDescription
mode'all' | 'include' | 'exclude''all'Which links to intercept. 'all' catches every <a> click; 'include' only fires on matched selectors; 'exclude' fires on all links except matched selectors.
selectorsstringCSS 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.

By default all links trigger the exit animation. Pass skipHref to 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"] });