DEV Community

Cover image for React 19 Micro-Interactions Without Layout Jank
Mark Yu
Mark Yu

Posted on • Edited on

React 19 Micro-Interactions Without Layout Jank

Micro-interactions are easy to overdo.

The good ones make the UI feel responsive. The bad ones delay the user, shift layout, or turn every click into a tiny fireworks show.

My rule is simple:

Animate feedback, not uncertainty.

Start With the Cheapest Interaction

For a button, CSS is enough:

export function SaveButton({ saving }) {
  return (
    <button className="save-button" disabled={saving}>
      {saving ? "Saving..." : "Save changes"}
    </button>
  );
}
Enter fullscreen mode Exit fullscreen mode
.save-button {
  transform: translateY(0);
  transition:
    transform 140ms ease,
    background-color 140ms ease,
    box-shadow 140ms ease;
}

.save-button:hover {
  transform: translateY(-1px);
}

.save-button:active {
  transform: translateY(0);
}
Enter fullscreen mode Exit fullscreen mode

No layout properties. No JavaScript animation. No drama.

Avoid Animating Layout

Prefer:

  • transform
  • opacity
  • color
  • shadow, carefully

Be careful with:

  • height
  • width
  • top
  • left
  • margin

Those can trigger layout work and make the UI feel janky.

Optimistic Feedback

For React apps, many interactions feel better when the UI responds before the server round trip finishes.

function LikeButton({ initialLiked }) {
  const [liked, setLiked] = useState(initialLiked);
  const [pending, setPending] = useState(false);

  async function toggle() {
    const next = !liked;
    setLiked(next);
    setPending(true);

    try {
      await fetch("/api/like", {
        method: "POST",
        body: JSON.stringify({ liked: next }),
      });
    } catch {
      setLiked(!next);
    } finally {
      setPending(false);
    }
  }

  return (
    <button className={liked ? "liked" : ""} onClick={toggle} disabled={pending}>
      {liked ? "Liked" : "Like"}
    </button>
  );
}
Enter fullscreen mode Exit fullscreen mode

The important part is rollback. Optimistic UI without rollback is just lying with confidence.

Respect Reduced Motion

@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
Enter fullscreen mode Exit fullscreen mode

I usually scope this more carefully in production, but the principle matters: motion should not be forced.

My Interaction Checklist

Question If no
Does it communicate state? remove it
Does it keep layout stable? redesign it
Does it work with keyboard? fix focus state
Does it respect reduced motion? add fallback
Does it still feel fast on low-end devices? simplify

React 19 Angle

React 19 makes async UI patterns cleaner, but it does not automatically make motion good.

Use React for state and transitions. Use CSS for simple visual feedback. Reach for animation libraries only when the interaction is complex enough to justify them.

Final Thought

Premium UI is not about more animation. It is about the interface responding at the exact moment the user expects it to.

Which micro-interaction in a product made the UI feel genuinely better to you?

Top comments (0)