All articles
Design & UXJune 30, 2026 6 min read

Stop Animating Everything: A Motion Budget That Respects Users and CPUs

Most product UIs animate too much, too long, and at the wrong easing. Here's the motion budget we use to keep interfaces feeling fast, accessible, and intentional.

Open most B2B dashboards in 2026 and you'll find a card that fades in over 600ms, a sidebar that slides with a bouncy spring, a tooltip that scales from 0.8, and a chart that animates every single bar on every single render. None of it helps the user finish their task. It just makes the product feel slower than it is.

We've spent the last few years tightening motion across client products, and the pattern that keeps working is a motion budget: a small set of rules about what's allowed to move, for how long, and why. Here's how we build one.

Why motion needs a budget

Animation isn't free. Every transform costs frame time, every fade competes with the user's attention, and every spring delays the moment they can click the next thing. The best motion designers we've worked with treat duration the way good writers treat adjectives — suspicious by default.

A motion budget answers three questions before a single keyframe is written:

  1. What is this animation telling the user? (state change, spatial relationship, feedback, delight)
  2. How long can it take before it starts feeling slow?
  3. What happens when the user has prefers-reduced-motion on, or is on a low-end Android?

If an animation can't answer question one, it shouldn't ship.

The duration ladder

We use a four-rung ladder for durations. It's opinionated, but it survives contact with real products.

TierDurationUse for
Instant80–120msHover, focus, button press, tooltip show
Quick160–200msDropdowns, popovers, small state changes
Standard240–320msModals, drawers, page transitions
Deliberate400–500msOnboarding moments, success celebrations, one-off reveals

Anything above 500ms in a productivity UI is almost always wrong. If a designer asks for 800ms on a sidebar slide, the honest question is: what is the user looking at for the other 700ms after they already understood the panel opened?

The 2:1 enter/exit ratio

Exits should be roughly half the duration of enters. Users have already processed the element; they don't need another 300ms of fade to say goodbye.

:root {
  --motion-quick: 180ms;
  --motion-quick-exit: 90ms;
  --motion-standard: 280ms;
  --motion-standard-exit: 140ms;
}

.dialog[data-state='open'] {
  animation: dialog-in var(--motion-standard) var(--ease-out);
}
.dialog[data-state='closed'] {
  animation: dialog-out var(--motion-standard-exit) var(--ease-in);
}

This one change alone makes most UIs feel noticeably snappier without anyone being able to articulate why.

Easing: stop using ease-in-out for everything

ease-in-out is the default in most tools, and it's wrong most of the time. It makes things feel sluggish on both ends.

Our working set:

  • ease-out (cubic-bezier(0.2, 0, 0, 1)) — for things entering the screen. Fast start, gentle settle. The element is arriving; the user wants to see it.
  • ease-in (cubic-bezier(0.4, 0, 1, 1)) — for things leaving. Quick exit, no lingering.
  • ease-in-out (cubic-bezier(0.4, 0, 0.2, 1)) — only for things moving from A to B that stay on screen (a card reordering, a tab indicator sliding).
  • spring — sparingly. Springs are great for direct manipulation (drag-and-drop release) and terrible for routine state changes.

If you remember one thing: enter with ease-out, exit with ease-in, move with ease-in-out. That covers 90% of product motion.

Tokenise motion like you tokenise color

The same way you wouldn't let a developer hardcode #3b82f6 in a component, you shouldn't let them hardcode transition: all 0.3s ease. Motion belongs in your design tokens.

{
  "motion": {
    "duration": {
      "instant": "100ms",
      "quick": "180ms",
      "standard": "280ms",
      "deliberate": "440ms"
    },
    "easing": {
      "out": "cubic-bezier(0.2, 0, 0, 1)",
      "in": "cubic-bezier(0.4, 0, 1, 1)",
      "inOut": "cubic-bezier(0.4, 0, 0.2, 1)"
    }
  }
}

Feed that through Style Dictionary or whatever pipeline you use, and you end up with CSS variables, Tailwind theme values, and Framer Motion presets that all reference the same source of truth. When a designer wants to make the product feel snappier across the board, they change four numbers — not 400 components.

Tailwind config example

// tailwind.config.js
export default {
  theme: {
    extend: {
      transitionDuration: {
        instant: '100ms',
        quick: '180ms',
        standard: '280ms',
        deliberate: '440ms',
      },
      transitionTimingFunction: {
        out: 'cubic-bezier(0.2, 0, 0, 1)',
        in: 'cubic-bezier(0.4, 0, 1, 1)',
      },
    },
  },
}

Now a developer writes transition-colors duration-quick ease-out and they're inside the system without having to think about it.

Reduced motion is not an opt-out, it's a parallel design

The lazy implementation of prefers-reduced-motion is to set every duration to zero. That technically respects the OS setting and practically makes your app feel broken — modals appear with no indication of where they came from, dropdowns snap into place with no spatial logic.

A better default: keep opacity transitions, remove transforms.

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 120ms !important;
  }

  .motion-transform {
    transform: none !important;
  }
}

The user still gets a quick fade so they know something changed, but they don't get vestibular-triggering slides, scales, or parallax. This matters more than most teams admit — somewhere between 5% and 15% of users have reduced motion enabled in our analytics across recent projects, with the higher end on accessibility-conscious enterprise clients.

Performance: the 60fps rule has a footnote

Designers think in 60fps. Reality is less generous. On a mid-tier Android in battery saver mode, you're frequently looking at 30fps or worse. Your motion budget needs to assume that.

The practical rules we enforce in code review:

  • Only animate transform and opacity. Animating width, height, top, or background-color forces layout or paint on every frame.
  • No animations on scroll. If you absolutely must, use IntersectionObserver to trigger them once, not scroll listeners running 60 times a second.
  • Cap simultaneous animations. If a list of 30 items all stagger-fade in, you're not creating delight, you're creating jank. Stagger the first 5–8 visible items and let the rest appear.
  • will-change is a loaded gun. Useful for short-lived animations, terrible if left on permanently. Remove it after the animation ends.

Measuring it

Don't trust your MacBook Pro. Run the app on the cheapest Android phone in the office (or use Chrome DevTools' CPU throttling at 4x slowdown) and watch the Performance panel during your hero interactions. If you see a wall of long tasks during a modal open, your motion budget is being overspent.

A short war story

We inherited an e-commerce dashboard last year where the team had built a beautiful animated KPI grid: each card sprung in with a stagger, the numbers counted up over 1.2 seconds, and a subtle glow pulsed every 4 seconds to draw attention. It looked stunning in the demo.

In production, the operations team — the actual users — had set up a browser extension to block animations. They were checking the dashboard 40 times a day and every 1.2-second count-up was 1.2 seconds they didn't have.

We rebuilt it: cards appear instantly, numbers show their final value with a 200ms opacity fade, and the glow was deleted. Task completion time on the primary workflow dropped meaningfully and complaints stopped. Nobody mentioned the lost animations.

Motion has to earn its place. Most of it can't.

Where we'd start

If you're auditing an existing product, do this in order:

  1. Grep your codebase for hardcoded durations and easings. Every transition: and every Framer Motion duration prop. You'll find the spread is wider than you thought.
  2. Define four duration tokens and three easing tokens. That's it. Resist adding more.
  3. Pick the five most-used interactions (button hover, modal open, dropdown, toast, page transition) and rebuild them on the new tokens with the 2:1 enter/exit ratio.
  4. Add the reduced-motion media query and actually test it by enabling reduced motion in your OS, not just in DevTools.
  5. Throttle your CPU to 4x and run through the top three user flows. Anything that drops frames is over budget.

If you want a hand putting this kind of system in place across a design system and a real codebase, that's exactly the kind of work our design and engineering teams do together. Motion is the easiest part of a UI to get wrong and one of the most satisfying to get right.

#motion#accessibility#design-systems#frontend

Want a team like ours?

72Technologies builds production software for the kind of teams who actually read this blog.

Start a project