Spring Animations Explained: Stiffness, Damping and Mass
By Hizmedia · · 6 min read
Springs are why some interfaces feel physical and others feel like slideshows. Instead of moving from A to B over a fixed time, a spring pulls an element towards its target with a force, and the motion is whatever that force produces: a quick settle, a gentle overshoot or a lively wobble. Three numbers control it. Drag them below and watch what each one does.
Try it
Damping ratio 0.46: under-damped, so it overshoots and wobbles. Settles in about 1.04s.
<motion.div
animate={{ x: 240 }}
transition={{ type: "spring", stiffness: 170, damping: 12, mass: 1 }}
/>The ball and the curve use the same three values. The curve plots the ball's position over two seconds; the dashed line is the target.
What the three numbers do
A spring animation simulates a weight on a spring. Every frame, two forces act on it: the spring pulls it towards the target, harder the further away it is, and damping resists its speed, like friction.
stiffness: how strongly the spring pulls. Higher values make the motion faster and snappier.damping: how much the motion is resisted. Low damping lets it overshoot and oscillate; high damping makes it settle without overshooting, and very high damping makes it sluggish.mass: how heavy the thing being moved is. More mass makes it slower to start and stop, and adds momentum to any overshoot.
The damping ratio: wobble or no wobble
Whether a spring overshoots depends on the three values together, through the damping ratio: damping divided by 2 × √(stiffness × mass).
- Below 1, the spring is under-damped: it overshoots and oscillates before settling. Values around 0.5 to 0.8 feel lively without being silly.
- At 1, it's critically damped: the fastest possible settle with no overshoot at all.
- Above 1, it's over-damped: it creeps into place, which can feel heavy.
This is why doubling stiffness alone makes a spring bouncier as well as faster: the ratio drops. To keep the same feel while speeding it up, raise damping too.
Springs in Motion
In Motion, set type: "spring" on a transition and give it the physical values:
<motion.button
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
transition={{ type: "spring", stiffness: 400, damping: 17 }}
/>If you'd rather think in time, Motion also accepts a duration and a bounce instead, and works out the physics for you. bounce runs from 0 (no overshoot) to 1 (very springy).
transition={{ type: "spring", visualDuration: 0.4, bounce: 0.25 }}Why springs feel better when interrupted
The real advantage of springs shows when an animation is interrupted. If someone hovers off a button halfway through its grow, a fixed-duration tween has to start a fresh animation from a standstill, which can look like a hiccup. A spring keeps its current velocity and simply heads for the new target, so the motion stays continuous. That's why springs suit anything that follows the pointer, a finger or a drag: magnetic buttons, sliders, docks and tilting cards.
Picking values
- Snappy UI feedback, such as buttons and toggles: stiffness 300 to 500, damping 20 to 30.
- Panels, menus and layout changes: stiffness 200 to 300, damping 25 to 35, little or no overshoot.
- Playful elements that should wobble: stiffness 150 to 250, damping 8 to 14.
- Things that follow the pointer: lower stiffness (100 to 200) so they trail with some weight.
With reduced motion on, swap springs that move things across the screen for an instant change or a short fade. Small scale changes on press are generally fine to keep.