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 IFoundations04

Springs vs tweens

Time-based motion vs physics-based motion

A tween is cook-by-timer: set a duration, pick an easing, and the animation plays exactly that long every time. A spring is cook-by-feel: set the physics (stiffness, damping, mass), and the animation takes as long as the physics take. Most UI is built with tweens because they're predictable. But the animations that feel most alive (draggable panels, gesture feedback, everything on iOS) are almost always springs. Knowing which to reach for is a core skill.

#The idea

Tweens are time-based. You control duration and easing; the animation blindly runs to completion. Great for predictable, discrete transitions: modals opening, tooltips appearing, content entering. If you interrupt a tween, it snaps or restarts abruptly because the curve has no memory of velocity.

Springs are physics-based. You specify physical properties (how stiff the spring is, how much it resists motion, how heavy the object is) and the animation emerges from simulation. Duration is a consequence, not a setting. The motion settles when the physics settle.

Two properties make springs feel irreplaceable for interactive motion:

  • Interruptibility with velocity. If a user drags an element halfway and releases, a spring picks up with whatever velocity the drag had and continues naturally. A tween would snap from the current position back to the start, losing momentum. This is what makes Apple's Dynamic Island feel alive: you can push, pull, and interrupt it, and it always responds coherently.
  • Emergent character. By adjusting stiffness and damping, the same motion can feel floaty, bouncy, crisp, or heavy. You can dial in personality without keyframes.

The tradeoff: springs are unpredictable. You can't say this will land in exactly 300ms. That variability is a feature for gestures and a bug for tightly-scheduled choreography. Use tweens when timing matters; use springs when physics matters.

Canonical example

Drag a window on macOS, flick it, and release. It continues traveling, decelerates, and settles, all as one continuous motion, because a spring is doing the work. Now try to achieve the same effect with a tween: you'd need to estimate the release velocity, calculate a destination, pick an easing, and hope for the best. Springs are physics; everything else is approximation.

Stiffness controls the speed of return; damping controls whether it oscillates. Try stiffness 100 / damping 10 (floaty) vs stiffness 400 / damping 30 (crisp).

Controls

200.00
20.00
1.00

Elastic is a spring variant tuned for visible overshoot. Most production UI uses damping high enough to suppress oscillation entirely.

Controls

0.20
1.20s

#When it applies

  • Drag, flick, and gesture: anywhere the user's motion has velocity the system must continue.
  • Micro-interactions with personality: a button that squeezes and releases, a toggle that snaps into place.
  • Rearranging UI elements: list reordering, layout animations (lesson 10) use springs by default for a reason.
  • Anywhere you want motion to feel "alive." Springs are the difference between a checkbox that ticks and a checkbox that punches.

#When it doesn't

  • Scheduled choreography. If a sequence of three animations needs to complete in exactly 800ms total, tween. Spring duration is non-deterministic.
  • Content-long transitions. A modal opening in 300ms is better as an ease-out tween. Users expect modals to open at a known speed.
  • First-time entries. Springs shine when interrupted. An element that appears once, settles, and never moves again gets nothing extra from being a spring.

#Implementation

Motion accepts both tweens and springs on the same transition prop. Spring params can be expressed in two APIs:

SpringExamples.tsx
// Classic physics API (stiffness/damping/mass)
<motion.div
  animate={{ scale: 1.1 }}
  transition={{ type: "spring", stiffness: 300, damping: 24 }}
/>
 
// Apple's simpler API (duration/bounce)
<motion.div
  animate={{ scale: 1.1 }}
  transition={{ type: "spring", duration: 0.4, bounce: 0.2 }}
/>
 
// Compare to tween:
<motion.div
  animate={{ scale: 1.1 }}
  transition={{ duration: 0.2, ease: "easeOut" }}
/>
  • Apple's duration/bounce API (exposed by Motion since v11) is easier to reason about: bounce 0 = no overshoot, bounce 0.3 = playful.
  • For gesture interactions, always use springs. useSpring() preserves velocity through useMotionValue() chains.

#Craft notes

  • Damping > 20 suppresses most visible oscillation. If you don't want bounce, damping at least 20 with stiffness 200-400 is a safe range.
  • Mass at least 1 is the default. Increasing mass makes motion feel heavier and slower. Useful for large elements (modals, drawers) where you want weight.
  • Overshoot should be rare. Bouncy springs (bounce > 0.3) are attention-getting. Reserve for celebratory moments; don't sprinkle across every transition.
  • Apple's Dynamic Island is the canonical spring showcase. Every gesture it responds to uses springs with moderate damping. Study it.

#Exercises

  1. Match a spring to a tween. Configure a spring that takes ~300ms to settle (stiffness 300, damping 26 is close). Render it beside an ease-out 300ms tween. Which feels better?
  2. Interrupt both. Add a button that retriggers the animation mid-play. The tween restarts; the spring continues from current velocity. Feel the difference.
  3. Find a spring in the wild. Open iOS Control Center. Drag it halfway down and release. The entire panel's behavior is a spring simulation. Try to articulate what stiffness/damping range it's using.

#Study this in the wild

  • iOS Dynamic Island. Springs all the way down. Every interaction is interruptible, which is why it feels physical.
  • macOS Mission Control. Window tiling uses springs with high damping. Crisp, no bounce, but velocity-aware.
  • Notion's drag-to-reorder. Drops use a spring to settle. Interrupt mid-drop and it handles gracefully.

#Further reading

  • Matt Perry: The physics of springs.
  • Apple: Animating with the new spring API — why Apple moved from stiffness/damping to duration/bounce.
  • Josh Comeau: A friendly introduction to spring physics.
Lesson 03
Easing
Lesson 05
Anticipation

On this page

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

Built by David Umoru