UI Physics
Spring physics playground
Tune a spring by feel, then export it to Motion, React Spring, CSS linear(), SwiftUI and more.
- Damping ratio
- 0.45
- Settles in
- 1170 ms
- Peak
- 1.208
- Regime
- underdamped
Overshoots and rings before settling
Card
Modal
Button press
Tab indicator
transition={{
type: "spring",
stiffness: 180,
damping: 12,
mass: 1,
}}How it works
Tune
Stiffness, damping, mass and initial velocity.
Solve
Three closed forms, chosen by damping ratio.
Check
Curve, overshoot peak and the millisecond it settles.
Export
Eight targets, each marked exact or approximate.
Why UI Physics
Spring tools are tied to one framework, and the CSS ones quietly hand you a curve that cannot match what you just previewed.
Almost every spring playground belongs to one library. You tune a feel in a React Spring visualiser and then re-guess it by hand in Motion, or in CSS, or in SwiftUI, because the numbers do not carry across. The thing you actually tuned was a feel, and the feel is portable even when the config is not.
The CSS side has a sharper problem. A cubic-bezier can overshoot its target once. It cannot come back and overshoot again, which is exactly what a bouncy spring does. Tools that offer a bezier for any spring are giving you a curve that does not match their own preview, and you will not notice until the motion looks wrong in the build.
There is also a number nobody shows. When you budget an interaction, what you need is how long the motion takes to stop — not to look roughly finished, but to stay within a fraction of a percent of target. Without that readout, the sliders cannot tell you whether you built something responsive or something that drags.
It refuses to lie about cubic-bezier
When no bezier can match your spring, it says so and points at linear(), instead of emitting a curve that disagrees with the preview above it.
| Capability | Elsewhere | Here |
|---|---|---|
| Exports to more than one framework | No:Playgrounds are usually tied to their own library | Yes:Motion, React Spring, CSS, SwiftUI, Flutter |
| Correct past critical damping | Partly:A single underdamped formula breaks above it | Yes:Three closed forms, tested against numerical integration |
| Honest about cubic-bezier | No:A bezier is offered even for curves it cannot express | Yes:Refused for ringing springs, error stated otherwise |
| CSS linear() output | Partly:Available in dedicated generators, rarely elsewhere | Yes:Primary CSS output, simplified to stay pasteable |
| Settle time in milliseconds | No:Seldom shown | Yes:Solved in closed form, not eyeballed |
| Shareable link | Partly:Sometimes | Yes:Every parameter lives in the URL |
What it does
Drag three sliders until the motion feels right, then copy the config for whichever framework you are in. The same spring is translated to Motion, React Spring, CSS, SwiftUI and Flutter, so a feel you tuned once travels between platforms instead of being re-guessed on each.
The three numbers
Stiffness is how hard the spring pulls toward its target. Raise it and everything happens sooner. Damping is the resistance that bleeds energy out. Too little and the element rings like a plucked string; too much and it crawls. Mass is how much inertia there is to overcome — heavier elements start later and take longer to stop.
What actually determines the character of the motion is the ratio between them, called the damping ratio. Below one the spring overshoots and oscillates. At exactly one it reaches the target as fast as possible without ever passing it. Above one it eases in slowly and never overshoots at all.
Why a bouncy spring cannot be a cubic-bezier
A cubic-bezier easing curve can overshoot its endpoint once. It cannot come back and overshoot again, which is exactly what a bouncy spring does. So for any spring with real bounce, no cubic-bezier exists that matches it, and any tool that hands you one is giving you a curve that does not match its own preview.
The honest answer in CSS is linear(), which takes a list of sampled points and can therefore describe an oscillating curve exactly. It is supported across current browsers. Where a bezier genuinely does fit, this tool will give you one and show you the measured error; where it does not, it will say so instead of guessing.
Settle time
The number most worth knowing when budgeting an interaction is how long the motion takes to stop — not how long it takes to look roughly finished, but the point past which it stays within a fraction of a percent of its target. A transition that settles in four hundred milliseconds feels responsive. The same spring at nine hundred feels broken, and the sliders will not tell you which one you have built without that readout.