driftkit

Spring Physics 101

Every DriftKit component uses spring physics instead of CSS timing functions. Here's what that means, why it matters, and how to tune it.

The Problem with CSS Animations

CSS animations use bezier curves — mathematical functions that map time to progress. You specify a duration (say 300ms), an easing function (like ease-in-out), and the animation follows that exact path.

This works fine for simple transitions. But it breaks down when interactions get complex:

  • Can't interrupt. Hover mid-press? The animations queue up and fight.
  • Fixed duration. A tiny movement takes the same 300ms as a large one.
  • No momentum. Fast flicks feel the same as slow drags.
  • Feels robotic. The motion is mathematically perfect, which paradoxically makes it feel unnatural.

Spring vs Bezier: See the Difference

Spring vs Bezier Curve

Spring — interruptible, no fixed duration
CSS ease-in-out — fixed 500ms, can't interrupt

Notice how the spring overshoots and settles naturally, while the bezier curve just... stops. The spring feels like a real object.

How Springs Work

A spring animation simulates a physical spring. Instead of "go from A to B in 300ms," it says "pull toward B with this much force, resisting with this much friction."

Three parameters control everything:

stiffnessdefault: 100

How strong the spring pulls toward the target. Higher = snappier response. Think of it as the "urgency" of the animation.

Low (50-150): Lazy, floaty. High (400-1000): Snappy, immediate.

dampingdefault: 10

How quickly oscillation dies out. This is the "friction." Low damping = more bounce. High damping = smooth settle.

Low (5-15): Bouncy, playful. High (25-50): Smooth, controlled.

massdefault: 1

How "heavy" the animated element feels. Higher mass = more momentum, slower to start and stop.

Light (0.1-0.5): Quick, responsive. Heavy (2-5): Weighty, deliberate.

Try It Yourself

Adjust the sliders and hit Replay to see how each parameter affects the motion:

Interactive Spring

300

Higher = snappier, more force pulling toward target

30

Higher = less oscillation, settles faster. Lower = more bounce.

1

Higher = heavier, more momentum, slower to start/stop

{ type: "spring", stiffness: 300, damping: 30, mass: 1 }

DriftKit Presets

These are the spring presets used across DriftKit components. Format: stiffness/damping/mass

Preset Library

SnappyQuick, decisive. Buttons, toggles.
500/30/0.5
SmoothNatural, balanced. Modals, cards.
300/30/1
QuickFast, no overshoot. Tooltips, hovers.
500/40/0.3
BouncyPlayful, energetic. Notifications, badges.
400/15/0.8
HeavyWeighty, deliberate. Drawers, panels.
200/25/2

Rules of Thumb

01

Start with stiffness 300, damping 30. This is a solid default that works for most UI elements. Adjust from there.

02

Small elements should be snappier. Buttons, toggles, badges — use higher stiffness (400-600) and lower mass (0.3-0.5).

03

Large elements should be smoother. Modals, drawers, page transitions — use lower stiffness (200-300) and higher mass (1-2).

04

Overshoot adds personality. A little bounce (damping 15-25) makes UI feel alive. Too much feels broken.

05

Consistency matters. Use the same spring for similar interactions. Don't mix 5 different springs in one component.

06

Test with reduced motion. Always check useReducedMotion — some users need static or minimal animation.

Go Deeper