Duration & Delay
Control animation timing with duration in seconds and delay before start.
duration and delay are the two core timing properties in every AnimationConfig. Duration controls how long the animation runs; delay controls when it starts.
Duration
duration sets how many seconds the animation takes to complete. It accepts any positive number, including decimals.
| Property | Type | Default | Description |
|---|---|---|---|
duration | number | 0.5 | Seconds the animation takes to complete |
import { Motion } from "@motion.page/sdk";
// 0.3s — fast UI interaction
Motion("quick-fade", ".button", {
from: { opacity: 0 },
duration: 0.3,
}).play();
// 1.2s — slower scroll reveal
Motion("slow-reveal", ".hero", {
from: { opacity: 0, y: 60 },
duration: 1.2,
ease: "power2.out",
}).onScroll({ scrub: false, toggleActions: "play none none none" }); Duration 0 — Instant Snap
Setting duration: 0 makes the animation apply instantly with no transition. This is functionally equivalent to Motion.set().
// These two are equivalent
Motion("snap", ".box", {
to: { opacity: 0 },
duration: 0,
}).play();
Motion.set(".box", { opacity: 0 }); Prefer Motion.set() when the intent is clearly “apply immediately” — it’s more readable. Use duration: 0 when you want snap behaviour inside a multi-step timeline where other entries have duration.
Delay
delay sets how many seconds to wait before the animation begins. The element holds its initial state during the delay period.
| Property | Type | Default | Description |
|---|---|---|---|
delay | number | 0 | Seconds to wait before the animation starts |
Motion("delayed-entry", ".card", {
from: { opacity: 0, y: 30 },
duration: 0.6,
delay: 0.4,
ease: "power2.out",
}).play(); Combining Duration & Delay
Use both together to fine-tune when and how fast an animation runs:
Motion("entrance", ".modal", {
from: { opacity: 0, scale: 0.92 },
duration: 0.5,
delay: 0.2,
ease: "power2.out",
}).onPageLoad(); Delay with Stagger
When stagger is used, the per-element delay is added on top of the base delay. The first element starts at delay, the second at delay + stagger, the third at delay + 2 × stagger, and so on.
// Element 1 starts at 0.3s
// Element 2 starts at 0.3 + 0.08 = 0.38s
// Element 3 starts at 0.3 + 0.16 = 0.46s
// …and so on
Motion("list-reveal", ".item", {
from: { opacity: 0, y: 20 },
duration: 0.5,
delay: 0.3,
stagger: 0.08,
ease: "power2.out",
}).onScroll({ scrub: false, toggleActions: "play none none none" }); delay is useful here as a scene delay — a buffer before the staggered sequence begins, so it doesn’t fire the instant the trigger activates.
See Stagger for the full StaggerVars API and advanced ordering options.
API Reference
interface AnimationConfig {
duration?: number; // Seconds — how long the animation runs
delay?: number; // Seconds — how long to wait before starting
stagger?: number | StaggerVars; // Per-element delay, stacks on top of delay
// ...other props
} Timing Tips
UI interactions (hovers, clicks, toggles) — 0.2–0.4s. Fast enough to feel responsive, slow enough to be visible.
Standard transitions (modals, panels, toasts) — 0.4–0.6s. Balanced and polished.
Scroll reveals and entrance animations — 0.6–1.2s. Longer reads as deliberate and cinematic.
Stagger increments — 0.02–0.08s per element. Below 0.02s is imperceptible; above 0.12s starts feeling slow for most lists.
Common Mistakes
Using milliseconds instead of seconds. Duration is always in seconds. duration: 500 means 500 seconds, not 500ms. Use duration: 0.5 for half a second.
Forgetting that delay stacks with stagger. With delay: 0.5 and stagger: 0.1, the last element in a 10-item list starts at 0.5 + 0.9 = 1.4s. Factor this in when the animation needs to complete within a tight time window.
Related: Easing · Stagger · Core Concepts