Easing Functions

All easing curves — power, sine, expo, circ, back, elastic, bounce — with visual reference.

Easing shapes the acceleration curve of an animation — whether it glides smoothly, snaps sharply, overshoots, or bounces. Every AnimationConfig accepts an ease string.

Basic Usage

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

Motion("reveal", ".card", {
  from: { opacity: 0, y: 40 },
  duration: 0.6,
  ease: "power2.out",
}).onScroll({ scrub: false, toggleActions: "play none none none" });

The ease Property

PropertyTypeDefaultDescription
easestring"power1.inOut"Easing curve — lowercase family name + direction suffix

The format is "family.direction" in lowercase: "power2.out", "elastic.inOut", "back.in". Two values skip the direction suffix: "none" (linear, constant speed) and omitting ease entirely (uses the SDK default, equivalent to "power1.inOut").

Directions

All families except none accept three direction suffixes:

SuffixMeaningUse when
.inAccelerates — slow start, fast endExits, elements leaving the screen
.outDecelerates — fast start, slow endEntrances, reveals — most natural direction
.inOutSlow start, fast middle, slow endRepositioning, looping, symmetric transitions
typescript
ease: "power2.out"   // fast to slow — standard reveal ease
ease: "power2.in"    // slow to fast — exits and aggressive enters
ease: "power2.inOut" // symmetric — good for repositioning and loops

All Easing Families

FamilyFeelBest for
power1Gentle — closest to CSS easeSubtle UI motion, body text reveals
power2Moderate — the everyday workhorseScroll reveals, card entrances, most animations
power3Strong — punchy, confidentHero sections, modals, bold entrances
power4Very strong — dramatic onset/cutoffCinematic moments, high-impact exits
sineSmooth sinusoidal — lightest of allDelicate fades, floating loops
expoExtreme — near-instant snapDrawers, command palettes, high-contrast UIs
circCircular arc — mechanical, abruptSorting animations, precise layout changes
backSlight overshoot then settlesPlayful cards, buttons, landing animations
elasticMulti-oscillation springBadges, tooltips, success states
bounceDiscrete ball-drop bouncesGame UI, mascots, high-energy moments
roughJitter/shaking motionGlitch effects, error shakes, organic feel
slowPauses mid-range — emphasis beatDramatic pauses, attention-drawing loops
noneLinear — constant speedScrub animations, progress bars

Visual Comparison

Code Examples by Family

Power1–4

The power family covers the vast majority of UI animations. Strength scales with the number — power1 is barely perceptible, power4 has an almost instant onset or cutoff.

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

// power2.out — the default choice for scroll reveals
Motion("reveal", ".section", {
from: { opacity: 0, y: 30 },
duration: 0.6,
ease: "power2.out",
}).onScroll({ scrub: false, toggleActions: "play none none none" });

// power3.out — punchy hero entrance
Motion("hero", ".headline", {
from: { opacity: 0, y: 60 },
duration: 0.8,
ease: "power3.out",
}).onPageLoad();

// power4.in — aggressive exit for page transitions
Motion("exit", "body", {
to: { opacity: 0, y: -20 },
duration: 0.4,
ease: "power4.in",
}).onPageExit({ skipHref: ["anchor", "mailto"] });

Sine & Expo

sine is the gentlest curve of all families — nearly imperceptible at short durations. expo is the sharpest, producing a near-instant snap quality.

typescript
// sine.out — light, airy entrance for delicate elements
Motion("float", ".caption", {
from: { opacity: 0, y: 12 },
duration: 0.9,
ease: "sine.out",
}).play();

// expo.out — snappy drawer or panel that pops open
Motion("drawer", ".sidebar", {
from: { x: -320 },
duration: 0.5,
ease: "expo.out",
}).play();

Circ

circ follows a circular arc — sharper than power curves and more mechanical in feel.

typescript
// circ.inOut — list reordering with a crisp pivot
Motion("sort", ".item", {
to: { y: 80 },
duration: 0.45,
ease: "circ.inOut",
}).play();

Back — Overshoot

back.out travels slightly past the destination, then snaps back to rest. Creates a satisfying landing or pop effect.

typescript
// Pop-in with overshoot — modal or badge appears with snap
Motion("pop", ".badge", {
from: { opacity: 0, scale: 0.82 },
duration: 0.5,
ease: "back.out",
}).play();

// Hover lift with overshoot — cards feel springy on enter
Motion("lift", ".card", {
to: { y: -8 },
duration: 0.35,
ease: "back.out",
}).onHover({ each: true, onLeave: "reverse" });

Elastic — Spring

elastic.out oscillates multiple times before settling. Draws significant attention — use it for moments that deserve a spotlight.

typescript
// Notification badge springs into view
Motion("ping", ".notification-badge", {
from: { scale: 0, opacity: 0 },
duration: 0.7,
ease: "elastic.out",
}).play();

// Tooltip pops in with a spring
Motion("tooltip", ".tooltip", {
from: { opacity: 0, scale: 0.88 },
duration: 0.6,
ease: "elastic.out",
}).play();

Bounce — Ball Drop

bounce.out simulates discrete ball-bouncing steps. More mechanical and playful than elastic.

typescript
// Icon drops in with a bounce
Motion("drop", ".icon", {
from: { y: -60, opacity: 0 },
duration: 0.8,
ease: "bounce.out",
}).play();

Rough & Slow

rough adds jitter — useful for shaky, glitchy, or organic motion. slow decelerates strongly through the middle of its range, creating a natural pause for emphasis.

typescript
// Error shake — rough jitter on validation failure
Motion("shake", ".form-field", {
from: { x: -5 },
to: { x: 5 },
duration: 0.06,
ease: "rough",
repeat: { times: 8, yoyo: true },
}).play();

// Slow pulse — emphasis beat that draws the eye
Motion("pulse", ".cta-button", {
from: { scale: 1 },
to: { scale: 1.06 },
duration: 0.8,
ease: "slow.inOut",
repeat: { times: -1, yoyo: true },
}).play();

None — Linear

"none" moves at constant speed with no acceleration. The right choice for scrub animations and any motion where the position should map directly to a value without distortion.

typescript
// Scrubbed parallax — scroll position maps 1:1
Motion("parallax", ".bg-layer", {
from: { y: -80 },
to: { y: 80 },
ease: "none",
}).onScroll({ scrub: true });

// Progress bar — constant speed is the point
Motion("progress", ".bar", {
from: { width: "0%" },
to: { width: "100%" },
duration: 3,
ease: "none",
}).play();

When to Use Which Ease

Scroll reveals and entrancespower2.out or power3.out. A decelerating ease reads as the element arriving and coming to rest naturally.

Exits and page transitionspower2.in or power3.in. An accelerating ease looks like the element flying away rather than disappearing mid-movement.

Hover effectspower2.out on enter, power1.inOut or power2.in on leave. Keep hover duration short: 0.2–0.35s.

Looping and yoyo animationssine.inOut or power2.inOut. Symmetric curves restart without a jarring speed discontinuity.

Scrub / scroll-drivennone. Any other ease creates uneven, rubber-banding scrubbing.

Playful momentsback.out for mild snap, elastic.out for spring energy. Reserve these for moments that genuinely deserve attention.

Dramatic and cinematicexpo.out or power4.out. High-contrast onset/cutoff creates energy and intentionality.

Mechanical / precision UIcirc.inOut or expo.out. These feel direct and purposeful rather than casual.

API Reference

typescript
interface AnimationConfig {
  ease?: string;
  // "power1.out" | "power2.out" | "power3.out" | "power4.out"
  // "power1.in"  | "power2.in"  | "power3.in"  | "power4.in"
  // "power1.inOut" | "power2.inOut" | "power3.inOut" | "power4.inOut"
  // "sine.in"  | "sine.out"  | "sine.inOut"
  // "expo.in"  | "expo.out"  | "expo.inOut"
  // "circ.in"  | "circ.out"  | "circ.inOut"
  // "back.in"  | "back.out"  | "back.inOut"
  // "elastic.in" | "elastic.out" | "elastic.inOut"
  // "bounce.in"  | "bounce.out"  | "bounce.inOut"
  // "rough.in"   | "rough.out"   | "rough.inOut"
  // "slow.in"    | "slow.out"    | "slow.inOut"
  // "none"
}

Omitting ease uses the SDK default: equivalent to "power1.inOut".


Related: Duration & Delay · Stagger · Repeat & Yoyo