Spring Animation: The Physics of Natural UI Motion
Learn how spring animation works in UI design. Understand stiffness, damping, mass, and velocity. Build natural physics-based animations for React and SwiftUI.
Core Takeaway
Spring animation models UI motion using the physical behavior of a mass-spring-damper system, where a component's movement is governed by stiffness (how strongly it pulls toward rest), damping (how quickly it loses energy), and mass (how much inertia it carries). Unlike duration-based animations, springs automatically respond to user velocity and can be interrupted at any point without causing visual discontinuity.
Why Springs Feel More Natural Than Duration Curves
The physical world does not have concepts like "ease-in-out" or "cubic-bezier(0.4, 0, 0.2, 1)." Physical objects accelerate due to forces and decelerate due to friction. When a drawer slides open, it has momentum; when you release it, friction brings it to rest. Spring physics replicates this physical reality in software, which is why iOS UIKit, Android Motion Compose, and ExodeUI are all spring-first animation systems.
Spring Parameters Explained
Understanding each parameter lets you design exactly the physical feel you want.
Stiffness (Tension)
How strongly the spring pulls toward its resting value. High stiffness (600+) creates snappy, responsive UI like button press feedback. Low stiffness (100–200) creates slow, floaty motion suitable for page transitions or ambient floating elements.
Damping (Friction)
How much energy the spring loses per cycle. At critical damping, the spring reaches rest without oscillating. Underdamped springs (low friction) will overshoot and bounce. The ratio damping / (2 × sqrt(stiffness × mass)) determines whether you are underdamped, critically damped, or overdamped.
Mass
How much inertia the animated element carries. A higher mass makes the animation feel heavier and takes longer to change direction. Most UI animations keep mass at 1.0 and control feel through stiffness and damping.
Initial Velocity
If the user swipes or flings an element, the spring can be initialized with that gesture velocity, creating seamless continuity between gesture and spring settlement.
Practical Spring Presets for UI Components
These presets cover the most common UI interaction patterns.
- Button tap: stiffness 500, damping 30 — instant, snappy, minimal bounce
- Card expand: stiffness 280, damping 24, mass 1.2 — smooth, weighted expansion
- Drawer / sheet: stiffness 340, damping 28 — decisive, with slight settling
- Bouncy notification: stiffness 400, damping 18 — playful overshoot
- Page transition: stiffness 220, damping 22, mass 1.4 — cinematic, weighted
Production Implementation Snippet
import { useSpring, SpringConfig } from '@exodeui/react';
// Practical spring presets
const presets: Record<string, SpringConfig> = {
snappy: { stiffness: 500, damping: 30, mass: 1.0 },
smooth: { stiffness: 280, damping: 24, mass: 1.2 },
bouncy: { stiffness: 400, damping: 18, mass: 1.0 },
cinematic: { stiffness: 220, damping: 22, mass: 1.4 },
};
export function PhysicsCard({ open }: { open: boolean }) {
const { y, scale } = useSpring({
y: open ? 0 : 24,
scale: open ? 1 : 0.96,
...presets.smooth,
});
return (
<div style={{ transform: `translateY(${y}px) scale(${scale})` }}>
<p>Smooth physics-based card reveal</p>
</div>
);
}