Skip to content
Animation2 min read

Animations you can interrupt mid-flight, with no bounce

Tap a control twice and the animation shouldn't start over from zero. Here is how the motion on this site picks up where it left off, and why nothing on a control bounces.

Flip a toggle and the knob slides over. Flip it again halfway through. If the knob jumps back to the start and takes off from there, something feels broken, even if the full animation looks lovely.

That happens when the motion is a timed curve: 300 milliseconds from here to there. Change your mind halfway and the curve has no idea where the knob was or how fast it was going. It just starts over.

Picking up where it left off

A spring doesn't think in time, it thinks in destination. The knob wants to get somewhere, and at every instant it knows two things: where it is and how fast it's moving. Change the destination midway and both of those carry over; only the direction of the pull changes. The knob slows and turns around the way a heavy object would, with no jump and no restart.

I test it in an unglamorous way: I reverse the motion every 100 milliseconds for a full second and check that the position never jumps. One common trap is a CSS transition with an elastic curve. It feels springy, but it's still a timed curve. If someone can reverse it midway, it needs a real spring.

Why none of them bounce

A spring bounces or doesn't depending on how much you damp it. There is one exact point, critical damping, where it arrives as fast as it can without overshooting at all. The springs on the controls of this site (presses, knobs, tabs, sheets) sit at that point or above it, so they arrive and stay put.

Bounce on a button feels like a toy. You see it once and it's cute; you touch it every day and it gets in the way. So the motion file has exactly one spring that overshoots, and it has its own name so nobody grabs it by accident. It's for a celebration that happens once and ends, and it overshoots by about 1.5 percent. It never goes on a control.

Every spring lives in that one file. The ones on controls come from Material 3's motion scheme: one for movement and a stiffer one for opacity, so a fade never lags behind the move it belongs to. Things that follow the pointer or the scroll, like the parallax on the portrait on the home page, use hand-tuned springs, and those don't bounce either.

When something moves on screen, I want it to obey the hand. If the hand changes its mind, the motion changes with it.

OV

Obed Vargas

Builds AI agents and open-source tools