All notes

Motion should feel like a spring, not a timer

4 min read

Most interface motion is a timer: something moves from A to B in 300 milliseconds with an ease-out curve. It works, but it feels like a slideshow.

Real objects overshoot a little and settle. A spring curve copies that, and the difference is easy to feel even if you can't name it.

Springs in plain CSS

You no longer need a JavaScript animation library for this. The CSS linear() function takes a list of points, so a spring can be written once as a custom property and reused everywhere:

--ease-spring: linear(0, .16 3%, .82 9%, 1.19 14%,
  1.25 17%, 1.06 27%, .94 33%, 1 47%, 1.01 53%, 1);
.button { transition: transform .5s var(--ease-spring); }

Where it helps most

  • Buttons that squash when pressed and bounce back when released.
  • Menus whose links slide in one after another, each a few milliseconds late.
  • Small rewards, like a dice icon that spins a little too far before it lands.

Keep the springs for things the visitor touches. Big page-level movement with a lot of bounce gets tiring fast, and anyone who asks for reduced motion should get none of it.

NotesNext: Make it sharp on mobile first