I once sat in a usability test where a participant tapped a "Save" button four times before trusting it had worked. The save actually happened instantly. The interface just gave zero feedback, no color shift, no icon change, nothing to tell the brain the tap had registered. That's the entire case for micro-interactions in one sentence: they're not decoration, they're confirmation.
This guide covers where motion earns its place in an interface, the specific duration ranges that read as intentional, and the easing curves that separate a snappy interaction from a laggy one.
TL;DR: Micro-interactions confirm that an action registered, not that your product is fun. Keep them under 400ms, ease-out for anything appearing or responding to a tap, animate transform and opacity only, and skip the animation entirely on interactions where the outcome doesn't matter.
What Actually Deserves a Micro-Interaction?
Anything where the user needs confirmation that their input registered, and nothing else. Button presses, toggle switches, form validation, like and favorite buttons, loading states, and drag-and-drop feedback are the classic list, because each one leaves a user genuinely uncertain without a visible response.
What doesn't deserve one: routine navigation, static content reveals that would happen anyway, and anything a user does dozens of times a session where the animation itself becomes the friction. I've watched teams animate every list item on scroll into view, which looks great in a portfolio reel and drives daily users up the wall by day three.
How Long Should a Micro-Interaction Actually Run?
Shorter than most designers guess. Nielsen Norman Group's research on interface animation lands on 100-500ms as the window where motion registers as responsive rather than sluggish, with most micro-interactions clustering at the fast end of that range (Nielsen Norman Group, 2024).
| Interaction type | Duration | Easing |
|---|---|---|
| Button press/release | 100-150ms | Ease-out |
| Toggle switch flip | 150-200ms | Ease-in-out |
| Checkbox/radio fill | 150-200ms | Ease-out |
| Like/favorite animation | 300-400ms | Spring or ease-out-back |
| Form field validation | 200-300ms | Ease-out |
| Tooltip appear | 150-200ms | Ease-out |
| Loading spinner | Continuous | Linear (only exception) |
Would a user notice if you cut every one of these times by 30 percent? Usually no, and that's the point, faster almost always feels better in this category. Linear easing is the one deliberate exception on this list, because a loading spinner represents an unknown wait, not a discrete response, and constant-speed rotation reads as neutral rather than jarring.
Which Easing Curve Fits Which Moment?
Ease-out for anything appearing, responding to a tap, or entering the screen, it starts fast and settles, which mimics how physical objects come to rest. Ease-in for anything leaving or dismissing, since a sudden exit reads as more decisive than a lingering one. Ease-in-out for anything that moves between two states without a clear beginning or end, like a toggle switch.
Google's Material Design motion system backs this up directly, specifying emphasized easing curves that front-load deceleration for entering elements precisely because it makes interfaces feel more responsive to touch (Material Design, 2025).
Spring physics deserves a specific mention for like buttons and favorite icons, that little overshoot-and-settle bounce isn't just decoration, it mimics elastic material behavior and reads as more satisfying than a clean ease-out for interactions meant to feel delightful rather than purely functional.
Why Does Animating the Wrong CSS Property Cause Jank?
Because the browser has to do fundamentally different work depending on what you animate. Transform and opacity changes happen on the GPU compositor layer, the browser can skip layout and paint entirely and just redraw the composited layers. Animate width, height, margin, or top/left directly, and the browser recalculates layout on every single frame, which is where visible stutter comes from, especially on mid-range Android hardware.
My rule after years of performance debugging: if I can express the same visual effect with transform: scale() or translate() instead of changing actual box dimensions, I always do. A button "growing" on press should scale from 1 to 1.05, not animate its width and height properties. Same visual result, a fraction of the rendering cost.
Does Every Micro-Interaction Need Sound or Haptic Feedback Too?
No, but the best ones on mobile pair a visual cue with haptic feedback rather than relying on animation alone. A toggle switch that fires a light haptic tap alongside its flip animation feels more confirmed than the same animation in silence, because touch confirmation bypasses the visual attention bottleneck entirely. I reserve haptics for genuinely important confirmations, purchase completion, destructive action confirmation, not routine taps, or the phone starts buzzing constantly and users disable haptics site-wide out of self-defense.
Where Do These Rules Break Down?
Long lists are the first place. A 120ms scale on a button feels great once, and awful when a user is working through a table of 200 rows and every checkbox insists on its own little bounce. My working threshold is repetition count: past roughly ten repeats in a single task, I cut the duration in half or drop the motion entirely and leave a plain color change. Batch operations are the second failure point. Select forty items and fire forty staggered 300ms animations and the last item confirms almost a full second after the click, which reads as a bug rather than as polish.
Reduced-motion preferences are the third. I've reviewed plenty of production code where prefers-reduced-motion was handled by setting animation-duration to 0.01ms globally, which technically passes an audit and quietly kills the confirmation signal the interaction existed for. The better move is to keep the state change instant but visible, swap the 300ms fade for an immediate opacity jump, so a user who disabled motion still gets the feedback rather than nothing at all.
Common Mistakes I Keep Seeing
Chaining beats is the big one. A save button that pulses, then shows a spinner, then morphs into a checkmark, then fades back has spent maybe 900ms confirming something that happened in 40ms. Two beats is the ceiling for a micro-interaction, and honestly one is usually enough.
The second mistake is animating the wrong thing on the wrong element. A tooltip that scales from 0 to 1 grows from its center, which looks like a balloon inflating rather than a label appearing next to the cursor. Set transform-origin to the anchor edge and the same 150ms suddenly makes spatial sense. The third: using the same duration everywhere because it's a single design token. A tooltip at 150ms and a favorite heart at 350ms are different jobs, and forcing both to 250ms makes one sluggish and the other rushed.
The strongest micro-interactions disappear the moment you notice them. If a user can describe your button's hover state in detail after using the product for a week, it's probably drawing more attention than the actual task deserves. Aim for confirmation, not applause.