Springs for gestures

Spring anything dragged or interrupted; keep bounce 0.1 to 0.3.

Emil Kowalski@emilkowalski
Notice how when I drag it to dismiss there's a slight bounce at the end, but when I simply press the close button, there's no bounce at all. A drag requires some force, so adding a subtle bounce makes this transition feel more natural.
Jan 6, 2026Demo 3 ↓View on X ↗
Emil Kowalski@emilkowalski
swapped spring animaton for an ease-out one so it feels less abrupt.
Sep 23, 2026Cons ↓View on X ↗
Emil Kowalskiemilkowal.ski
interpolates value changes with spring-like behavior, rather than updating them immediately
Good vs great animationsDemo 2 ↓Read article ↗

From emil-design-eng, “Spring Animations”.

1. Interrupt it

Press Toggle twice quickly, or Interrupt at 150ms.

CSS keyframesBad
animation: 500ms var(--ease-out)
CSS transitionOkay
transition: transform 500ms
SpringGood
spring({ duration: 0.5, bounce: 0.2 })
<motion.div
  animate={{ x: open ? travel : 0 }}
  transition={{ type: "spring", duration: 0.5, bounce: 0.2 }}
/>

2. Follow the pointer

Move the pointer over both cards.

Raw valueBad
rotate = pointerX * 0.1
Spring-interpolatedGood
useSpring(pointerX * 0.1, { stiffness, damping })
bounce ≈ 0.50
import { useSpring } from "motion/react";

const rotateY = useSpring(pointerX * 0.1, { stiffness: 100, damping: 10 });

3. Drag versus button

Flick each sheet, then use its button.

One transitionBad
transform 400ms ease
Spring on dragGood
drag: spring · button: 300ms
Spring response for the drag release compared with the button's ease-out, over 1.2 seconds
dragbutton
function onRelease(velocity) {
  animate(y, target, { type: "spring", duration: 0.5, bounce: 0.2, velocity });
}

function onButtonPress() {
  animate(y, target, { duration: 0.3, ease: [0.32, 0.72, 0, 1] });
}

Why it matters, pros and cons

Why it matters

A spring carries velocity, so a new target bends the path instead of restarting.

Pros

  • Interruptions stay continuous.
  • A flick's velocity flows into the settle.
  • duration + bounce reads clearly.

Cons

  • Modals and dialogs usually want ease-out instead.
  • Button presses carry no force; bounce reads as wobble.
  • Functional data should update directly, not spring.