harveybutler.dev
All posts
1 min read

Fluid motion on the web without the jank

A few rules I follow to make interfaces feel smooth instead of busy.

Good motion is invisible. It guides your eye, confirms an action, and then gets out of the way. Bad motion makes you wait. Here's how I try to stay on the right side of that line.

Animate the cheap properties

The browser can animate transform and opacity on the compositor — no layout, no paint. Everything else risks jank.

/* cheap: composited */
.card { transition: transform 0.3s, opacity 0.3s; }
 
/* expensive: triggers layout */
.card { transition: width 0.3s, top 0.3s; }

Use spring, not linear

Linear easing feels robotic. A spring (or a nice cubic-bezier) gives motion a sense of weight.

transition={{ type: "spring", stiffness: 380, damping: 30 }}

Respect the user

Some people get motion sick. Always honour their preference:

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}

That's most of it. Keep it subtle, keep it fast, and let the content lead.