Skip to Content
DocsGuidesConfiguration

Configuration

There are three ways to dial in how a spring moves: raw physics, perceptual feel, or named presets. They all produce the same kind of motion — pick whichever you think in.

Physics

Every spring is defined by three constants:

OptionDefaultEffect
stiffness180Spring constant k. Higher = snappier.
damping12Damping coefficient c. Higher = less oscillation.
mass1Mass m. Higher = more sluggish.
import { spring } from "sprungdesign"; spring({ stiffness: 320, damping: 14, mass: 1, onUpdate });

The relationship between these is captured by the damping ratio ζ (createSpring(config).zeta):

  • ζ < 1underdamped: overshoots and oscillates (bouncy).
  • ζ = 1critically damped: fastest approach with no overshoot.
  • ζ > 1overdamped: slow, sluggish, no overshoot.

Feel

If you’d rather think like a designer than a physicist, use fromFeel to map duration + bounce onto those constants:

import { fromFeel, spring } from "sprungdesign"; spring({ ...fromFeel({ duration: 0.5, bounce: 0.3 }), onUpdate });
OptionDefaultEffect
duration0.5Perceptual duration in seconds — sets the natural frequency.
bounce0.2[-1, 1]: >0 bouncy, 0 critical (no overshoot), <0 sluggish.
mass1Mass.

The bounce extremes are clamped to a settling range, so ±1 stay usable rather than degenerate.

Presets

Four named configs cover most UI needs:

import { presets, spring } from "sprungdesign"; spring({ ...presets.bouncy, onUpdate }); // gentle · bouncy · stiff · lazy
PresetstiffnessdampingmassFeel
gentle120141Soft, a little overshoot
bouncy320141Snappy with a clear bounce
stiff420401Fast, almost no overshoot
lazy80261.4Slow and heavy

Settling thresholds

A spring is considered settled once it’s within both thresholds of the target, at which point it snaps exactly to the target and stops:

OptionDefaultSettles when…
restDistance0.05`
restVelocity0.05`

Raise them for large value ranges (e.g. animating thousands of pixels) so the spring doesn’t crawl the last fraction; lower them for sub-pixel precision.

Initial velocity

Seed a spring with motion using velocity — useful for handing off from a drag or fling gesture so the spring continues naturally:

spring({ velocity: 600, onUpdate }); // already moving at 600 units/sec

Next steps

Last updated on