Spring Animation
Physics-based motion that simulates a spring — overshooting the target slightly and oscillating before settling — producing natural, organic movement.
Plain English
Springs feel alive because they mimic the physical world. When you flick a card away on iOS or drag a drawer open, the motion does not end abruptly at the destination — it overshoots, bounces back, and settles. That final wobble is what makes the animation feel heavy and real rather than mechanical. Springs are defined by three parameters: mass (how heavy the object feels), stiffness (how tight the spring is), and damping (how quickly it loses energy). High stiffness with low damping produces a snappy, bouncy feel; low stiffness with high damping produces a slow, heavy drag. Unlike duration-based easing curves, springs naturally adapt their timing to the distance traveled — a short drag finishes faster than a long one, which matches how physical objects behave.
Technical
In CSS, spring-like behavior is approximated with cubic-bezier — a bouncy variant is cubic-bezier(0.34, 1.56, 0.64, 1). True physics springs require JavaScript: Framer Motion uses spring({ stiffness: 300, damping: 20, mass: 1 }); React Spring uses config.wobbly or { tension: 280, friction: 20 }. iOS/SwiftUI uses .spring(response:dampingFraction:blendDuration:). Web Animations API supports linear() easing (Chrome 113+) for custom spring curves. Common starting points: stiff/snappy UI = stiffness 400–600, damping 25–35; soft/floaty = stiffness 80–150, damping 10–15. Always pair with @media (prefers-reduced-motion: reduce) — set duration to near-zero or switch to a simple ease-out.
Live Demo
Spring vs Linear Easing
Click the button to animate both boxes. Spring easing overshoots slightly before settling.
transition-timing-function: linear
cubic-bezier(0.34, 1.56, 0.64, 1)
Spring easing feels alive — the overshoot mimics real-world physics and mass.
Usage
✓ Good usage
A modal sheet that springs up from the bottom with stiffness 250 and damping 22 — it slightly overshoots its final position and settles back, giving a tactile sense of weight and physicality.
✗ Bad usage
A navigation bar that springs into place on every page load with a high-amplitude wobble — the constant bounce distracts from content and trains users to feel nauseated rather than delighted.
Recommended values
- Snappy button/chip feedback: stiffness 400–600, damping 30–40
- Modal/sheet entrance: stiffness 200–300, damping 20–28
- Soft drag-and-drop drop: stiffness 80–150, damping 12–18
- CSS approximation: cubic-bezier(0.34, 1.56, 0.64, 1)
- Overshoot scale at peak: 1.05–1.15× for micro-interactions
- Always: prefers-reduced-motion override removes bounce entirely
Common mistakes
- Too much overshoot (underdamped spring) — a menu that bounces 3–4 times looks broken, not polished.
- Using spring for accessibility-sensitive elements without a prefers-reduced-motion override — oscillating motion is a known vestibular trigger.
- Applying spring to every element on a page — spring is a seasoning, not a default; reserve it for primary interactive surfaces (modals, drawers, cards) where physicality adds meaning.
AI Prompt Example
Copy this into Claude, Cursor, Bolt, or v0.
Animate the bottom sheet using a spring with stiffness: 260, damping: 22, mass: 1 (Framer Motion). The sheet should enter from the bottom and slightly overshoot its resting position before settling. Add a spring exit at half the stiffness (130) for a softer close. Wrap all motion in a prefers-reduced-motion check — if the user prefers reduced motion, use a simple 200ms ease-out instead.