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
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
| Property | Type | Default | Description |
|---|---|---|---|
ease | string | "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:
| Suffix | Meaning | Use when |
|---|---|---|
.in | Accelerates — slow start, fast end | Exits, elements leaving the screen |
.out | Decelerates — fast start, slow end | Entrances, reveals — most natural direction |
.inOut | Slow start, fast middle, slow end | Repositioning, looping, symmetric transitions |
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
| Family | Feel | Best for |
|---|---|---|
power1 | Gentle — closest to CSS ease | Subtle UI motion, body text reveals |
power2 | Moderate — the everyday workhorse | Scroll reveals, card entrances, most animations |
power3 | Strong — punchy, confident | Hero sections, modals, bold entrances |
power4 | Very strong — dramatic onset/cutoff | Cinematic moments, high-impact exits |
sine | Smooth sinusoidal — lightest of all | Delicate fades, floating loops |
expo | Extreme — near-instant snap | Drawers, command palettes, high-contrast UIs |
circ | Circular arc — mechanical, abrupt | Sorting animations, precise layout changes |
back | Slight overshoot then settles | Playful cards, buttons, landing animations |
elastic | Multi-oscillation spring | Badges, tooltips, success states |
bounce | Discrete ball-drop bounces | Game UI, mascots, high-energy moments |
rough | Jitter/shaking motion | Glitch effects, error shakes, organic feel |
slow | Pauses mid-range — emphasis beat | Dramatic pauses, attention-drawing loops |
none | Linear — constant speed | Scrub 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.
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.
// 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.
// 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.
// 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.
// 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.
// 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.
// 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.
// 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 entrances → power2.out or power3.out. A decelerating ease reads as the element arriving and coming to rest naturally.
Exits and page transitions → power2.in or power3.in. An accelerating ease looks like the element flying away rather than disappearing mid-movement.
Hover effects → power2.out on enter, power1.inOut or power2.in on leave. Keep hover duration short: 0.2–0.35s.
Looping and yoyo animations → sine.inOut or power2.inOut. Symmetric curves restart without a jarring speed discontinuity.
Scrub / scroll-driven → none. Any other ease creates uneven, rubber-banding scrubbing.
Playful moments → back.out for mild snap, elastic.out for spring energy. Reserve these for moments that genuinely deserve attention.
Dramatic and cinematic → expo.out or power4.out. High-contrast onset/cutoff creates energy and intentionality.
Mechanical / precision UI → circ.inOut or expo.out. These feel direct and purposeful rather than casual.
API Reference
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