Duration and easing scale: 100–500 ms, ease-out to enter, ease-in to leave
Concrete duration ranges and cubic-bezier curves for UI and marketing motion, grounded in Material 3 tokens and usability research, with rules for choosing by distance, size and frequency.
Overview
What: A default timing and easing vocabulary so motion feels quick, consistent, and physically plausible.
Why: Usability research places most UI animation between roughly 100 and 500 ms: under ~100 ms changes read as instant or jarring, above ~500 ms they feel like waiting. Mature design systems converge on similar numbers (Material 3 spans 50–1000 ms in 16 tokens; Atlassian uses 50–150 ms for interactions and 150–400 ms for transitions). Linear timing looks mechanical for spatial movement; asymmetric curves read as responsive.
Use when: choosing values for any transition, animation, or spring on web or native.
Do not use these limits for scroll-scrubbed animation (duration is driven by scroll distance, not time) or for ambient loops, which follow the pause/stop rules instead.
Implementation
- Pick duration by size and distance:
- Micro feedback (toggle, checkbox, button press): 50–150 ms, visible within 100 ms (Carbon 70/110/150).
- Hover-in (colour, opacity, shadow, lift): 150–200 ms, ceiling 200 ms (real-site median 180 ms).
- Small component change (tooltip, menu, chip, accordion; roughly ≤ 200 px of travel, a rule of thumb): 150–250 ms.
- Medium surfaces (modal, drawer, card expand, tab panel): 200–300 ms to open, 150–250 ms to close (NN/g modals 200–300 ms).
- Full-screen or long travel (page transition, sheet covering viewport): 300–450 ms; treat 500 ms as a ceiling for anything the user waits on.
- Entrances may be ~20–50% longer than exits of the same element (e.g. 300 ms in, 200–250 ms out; NN/g); exits should get out of the way.
- Pick easing by direction:
- Entering / arriving: decelerate —
cubic-bezier(0.05, 0.7, 0.1, 1)(M3 emphasized decelerate) orcubic-bezier(0, 0, 0, 1)(standard decelerate). - Leaving: accelerate —
cubic-bezier(0.3, 0, 0.8, 0.15)(emphasized accelerate) orcubic-bezier(0.3, 0, 1, 1). - Moving on-screen A→B: standard —
cubic-bezier(0.2, 0, 0, 1). - Colour/opacity-only effects: standard or plain
ease-out; linear only for continuous loops, progress bars and scroll-scrubbed timelines.
- Entering / arriving: decelerate —
- Springs for direct manipulation. When motion continues a gesture (drag, swipe, fling), use a spring so velocity carries over. Critically damped or slightly under-damped (damping ratio 0.8–1.0) for UI; bouncy (<0.7) only for playful brand accents. CSS can approximate a spring with
linear()stops (Baseline since late 2023). - Scale with repetition. An effect seen 50 times a session should sit at the bottom of its range.
- Encode, don't hard-code. Expose these as tokens (
motion-design-tokens; house tokens fast 150 / base 250 / slow 400 ms, matching Carbon 150/240/400) and forbid raw ms values in components via lint or review.
.menu { transition: opacity 150ms cubic-bezier(0,0,0,1), transform 200ms cubic-bezier(0.05,0.7,0.1,1); }
.menu[data-state=closed] { transition-duration: 120ms, 150ms; transition-timing-function: cubic-bezier(0.3,0,0.8,0.15); }
- Cross-check against three independent numeric anchors rather than one table: NN/g places most UI animation at 100–500 ms (≈ 100 ms for simple feedback, 200–300 ms for larger changes; 500 ms starts to feel like a drag); Atlassian uses 50–150 ms for interactions and 150–400 ms for transitions; Material Design 1 (m1.material.io) used 195–400 ms (enter 225, leave 195, large/full-screen 375, "over 400 ms may feel too slow", desktop 150–200). They converge on the same order of magnitude — treat any single number as a starting point, not a spec.
- The halve-twice heuristic. A useful review heuristic: if a duration feels long, try halving it, then halving again (a 4 s fade becomes 1 s). It is a rule of thumb, not a measured bias.
- Ready-to-use curves (from the legacy Material v1 static reference; current M3 tokens differ — verify): standard
cubic-bezier(0.4, 0, 0.2, 1)for on-screen point-to-point; decelerationcubic-bezier(0, 0, 0.2, 1)for entering; accelerationcubic-bezier(0.4, 0, 1, 1)for exiting; sharpcubic-bezier(0.4, 0, 0.6, 1)for quick temporary elements. Define your own three (--ease-out,--ease-in,--ease-in-out) rather than the CSS keyword defaults. - Asymmetric hover timing is a concrete technique: e.g. 150–200 ms on hover-in and a relaxed 250–400 ms on hover-out (judgement default), on the same element — entrance and exit rarely deserve identical timing.
- Never ease-in on interactive feedback (button press, first response to a tap): the slow start reads as lag. Ease-in is for elements that end off-screen or invisible only (
motion-spring-vs-tween-selection). - Token health — the 80/20 rule and one dominant curve: ≥ 80% of transitions in a codebase should use the token durations/curves; if bespoke curves exceed 20%, fix the token set, not the components. Go further on marketing and product surfaces: pick one primary curve (
--ease-standard) and reuse it for colour, fill, stroke, opacity and transform alike — coherence is perceived even when no single transition is noticed, and it reads as product quality. Reserve a second curve only for a named category (entrances), and never run three or more curves without a written taxonomy. House defaults: 150–200 ms for hover, 150–250 ms for other state changes, 300–400 ms for large-element entrances (one hero reveal may run to 600 ms). - Synthesised starting rule from the three anchors: start most UI motion in the 150–400 ms range, err shorter, keep exits ≤ entrances, and treat any single number as a starting point for iteration rather than a spec — "feeling right" matters more than the exact number.
- Spring feel with no JS: the CSS
linear()easing function (Baseline Widely available since December 2023) takes many stop points and approximates a spring or bounce baked at author time — good for hover/press feel; it cannot carry live gesture velocity, so drag release still wants a physics spring (motion-spring-vs-tween-selection). - Speed as the aesthetic. If the product's promise is speed or efficiency (dev tools, issue trackers, terminals), slow or theatrical motion contradicts the pitch. Cap UI micro-interactions at 150–200 ms, ease-out only, no bounce, no spring-heavy entrances on the marketing site and no scroll-triggered reveals that slow reading; test on low-powered hardware so the "fast" grammar survives the target device. Inappropriate for brand-led, luxury or editorial contexts where pacing conveys craft. The strategic layer — how much motion identity a marketing site should spend at all — lives in
web-marketing-motion-identity-budget; keep the two in step.
Verification
- No interactive transition exceeds 500 ms (grep CSS/JS for durations > 500 outside hero/scroll/loop code).
- Hover/press feedback ≤ 200 ms; press feedback visible within 100 ms.
- Entering elements use a decelerating curve; exiting elements use an accelerating curve; no
linearon spatial UI movement. - Gesture-driven motion uses springs and inherits release velocity (fling a sheet: it should not restart from zero speed).
- Set the Chrome DevTools Animations panel to 25% (or 10%) and confirm curves match intent.
- Grep transitions: ≥ 80% use token durations/curves; no
ease-inon:active/press states. - Any animation > 500 ms has a written reason (narrative, scrubbed, or large-distance).
- One
--ease-standardcurve covers ≥ 80% of transitions; every additional curve maps to a named category. - Speed-positioned products: no micro-interaction exceeds 200 ms; no bounce/spring entrances on marketing pages.
Sources:
- https://www.nngroup.com/articles/animation-duration/
- https://github.com/material-components/material-components-android/blob/master/docs/theming/Motion.md
- https://atlassian.design/foundations/motion
- https://emilkowal.ski/ui/great-animations
- https://developer.mozilla.org/en-US/docs/Web/CSS/easing-function/linear
- https://www.smashingmagazine.com/2019/02/animation-design-system/
- https://valhead.com/2016/05/05/how-fast-should-your-ui-animations-be/
- https://24ways.org/2014/five-ways-to-animate-responsibly/
- https://www.joshwcomeau.com/animation/css-transitions/
- https://m1.material.io/motion/duration-easing.html
- https://www.joshwcomeau.com/animation/linear-timing-function/
- https://carbondesignsystem.com/elements/motion/overview/
Limitations
- Ranges are guidance, not measured optima for every audience; older users and novices may benefit from the upper end, power users from the lower end.
- Perceived speed depends on distance and screen size: the same 300 ms feels faster on a phone than across a 27" monitor, so large-screen transitions may need +50–100 ms.
- M3's emphasized easing is technically a path, not a single cubic-bezier; the decelerate/accelerate halves quoted here are the practical web approximations.
- Springs have no fixed duration; QA must judge settle time (target visually settled < 500 ms for UI).
- The cubic-bezier values cited are from a legacy platform reference chosen because it is static and citable; current design-system tokens may differ — re-verify before quoting them as a platform's rule.
- Values verified 2026-09-26: 34 checked — 6 against platform docs, 19 against published guidelines, 5 benchmarked against real-site practice, 4 against house policy and rulings. Remaining judgement defaults are marked as such in the text. The ≤ 200 px travel boundary, the hover-out range and the large-screen allowance are judgement defaults.