Moro
Gallery
IFoundations
01Why motion exists in UI
02Timing & duration
03Easing
04Springs vs tweens
IIExpression
05Anticipation
06Follow-through & overlapping action
07Squash, stretch & impact
08Arcs
IIIEngineering
09Performance
10Layout animations & FLIP
11Interruptibility & interaction
12Accessibility & restraint
Tier IIExpression05

Anticipation

Preparing the eye for motion about to happen

Before anything big happens, something small moves in the opposite direction. A batter pulls back before swinging; a cat crouches before pouncing; a menu pulls in slightly before sliding out. Your eye is told that motion is about to happen. Without it, interfaces feel abrupt, even when the timing is technically correct. Anticipation is the act of signaling motion about to begin: a cognitive pre-loader for your visual system.

#The idea

Human perception has a weak spot for the instant motion begins. We register where motion ended far more clearly than where it started. Anticipation fills that gap by giving the eye a preview frame: attention here, something's coming. Mechanically, it's a brief counter-motion before the main motion, in the opposite direction.

The simplest demo: a ball moves right. With anticipation, it first nudges left for ~150ms, then launches right. The physical read is that it winds up. Without anticipation, the same motion at the same duration feels mechanical: fast-forward, rather than thrown.

Anticipation is one of Disney's twelve foundational animation principles (Thomas & Johnston, 1981), and it carries cleanly into UI. Apple uses it heavily on iOS: the slide-to-unlock hint, swipe-to-dismiss previews, and even system notifications subtly pull back before committing.

Canonical example

Watch the iOS Mail app's swipe-to-delete. As your finger begins a swipe, the row pulls slightly back toward its original position before committing to the swipe animation. That counter-motion is anticipation telling you: this is where motion is headed.

Tune the pullback amount from 0 (no anticipation) to 25% of travel. Under 5% is invisible; over 15% looks cartoonish.

Controls

20.00px
0.20
0.80s

#When it applies

  • Motion is discrete and announced: a modal opening, a message flying away, a card expanding.
  • Clear directional intent benefits from signaling. The user should feel which way things will go.
  • Duration of at least 200ms: the pullback needs time to register visually.
  • System-initiated motion rather than user-direct motion.

#When it doesn't

  • Continuous motion: scrolling, dragging. The user's ongoing input is the anticipation.
  • User directly caused the motion: a tap that expands a button shouldn't pull back first; the tap itself is the anticipation.
  • High-frequency interactions: adds ~100ms that compounds into friction across a session.
  • Under 150ms duration: no time for the prep to land.
Common mistake

Adding anticipation to hover states. The button hops backward before expanding. Feels slow, not alive. Fix: let the click be the anticipation; animate cleanly from there.

#Implementation

Motion's keyframe + times API splits the timeline into phases:

AnticipationDemo.tsx
<motion.div
  animate={{ x: [0, -10, 100] }}              // 3 keyframes: rest, pullback, launch
  transition={{
    duration: 0.8,
    times: [0, 0.2, 1],                        // first 20% = pullback
    ease: [[0, 0, 0.58, 1], [0.25, 0, 0.35, 1]], // per-segment easing
  }}
/>
  • Per-segment ease array lets the pullback ease-out (prep) and the main motion ease-in (release): the most natural rhythm.
  • CSS @keyframes can express this too, but loses interruptibility. If the motion might be canceled mid-anticipation, stay in Motion.

#Craft notes

  • Pullback distance should be disproportionately small. 10% of total travel is almost always right. The asymmetry is what reads as real.
  • Heavy objects anticipate more than light ones. A modal pulling back slightly before opening feels right because modals are heavy. A tooltip doing the same looks silly.
  • Anticipation pairs with squash & stretch (lesson 7). Together they read as fully alive. Anticipation alone can feel mechanical.
  • The return trip shouldn't anticipate. If something anticipates on entry, it should exit cleanly. Otherwise every motion has two beats.
  • Anticipation is not overshoot. Overshoot is at the end of motion (the spring bounces past the target). Anticipation is at the start (preparation before launch). Different principles, different purposes.

#Exercises

  1. Spot it in the wild. Find anticipation in three real apps (iOS, macOS, web). Note pullback distance as a percentage of total travel and whether you'd call it subtle, appropriate, or heavy-handed.
  2. Tune to match. Configure the demo to match: Apple Podcasts' "mark as played" swipe, Linear's issue panel open, Notion's page-open sweep.
  3. Make it wrong. Take a demo where anticipation works and break it: too much pullback, too long, on the return trip. Articulate why each feels off.

#Study this in the wild

  • iOS Mail: swipe to delete. Row pulls back slightly before committing. Perfect calibration.
  • macOS Dock magnification. Icons slightly shrink before scaling up on hover. Subtle anticipation.
  • Linear's issue panel open. Modest pullback before the slide. Shows up on sufficiently large transitions.

#Further reading

  • Raphael Salaja: 12 Principles of Animation for UI — concise modern adaptation of Disney's principles.
  • Frank Thomas & Ollie Johnston: The Illusion of Life — the foundational text (1981).
  • Motion: Keyframe animations with times.
Lesson 04
Springs vs tweens
Lesson 06
Follow-through & overlapping action

On this page

The ideaWhen it appliesWhen it doesn'tImplementationCraft notesExercisesStudy this in the wildFurther reading

Built by David Umoru