UI Motion Design: Give Every Animation a Job Description

UI Motion Design: Give Every Animation a Job Description
Author
Richard Le Peurian Cross
I'm a technical lead with a background in design, front-end development and marketing, focused on building thoughtful digital experiences that balance creativity, usability and solid engineering.
Published

Animation gets added as polish and removed as a performance fix. Give every piece of UI motion a job, and timing, rendering and reduced-motion choices start to make themselves.

Picture a hypothetical product team. In one sprint, someone adds a flourish to the cards on a dashboard: hover, and each card lifts a few pixels while its shadow blooms underneath. It looks lovely in the demo. A few sprints later, a developer profiles a page that stutters on a mid-range laptop, finds the shadow repainting on every frame and deletes the lot. The pull request is approved within minutes. Nobody objects, because nobody can say what the animation did.

That quiet deletion is the tell. Decorative motion has no defence when performance review comes round. Purposeful motion does, because removing it breaks something people notice: they lose track of where a panel went, or tap a button twice because nothing confirmed the first press.

So treat every animation like a hire. Before it ships, it needs a job description, and if it cannot name its job, it should not ship. This sounds like bureaucracy for sparkles, but the job turns out to settle almost every other decision in UI motion design: how long the motion lasts, how it accelerates, which CSS properties it touches and what it becomes when a user asks for less movement.

Four Jobs Worth Applying Motion To

There are four roles motion can fill in a product interface, and most good UI animation is doing at least one of them:

  • Orientation. Showing where something came from or went. A settings panel that slides in from the right edge tells users it lives just off-screen there, and that sending it back is how to leave. Over time, these cues build a spatial model of an interface that is, strictly speaking, a flat rectangle of pixels.
  • Continuity. Keeping an object recognisable while it changes. When a card expands into a detail view, motion lets the eye follow one thing growing, so the change reads as the same object rather than a fresh page to be scanned from scratch.
  • Feedback. Confirming that an action registered: the pressed state of a button, the tick drawing into a checkbox. Feedback overlaps heavily with how transitions shape perceived speed, which deserves its own treatment.
  • Attention. Directing the eye to something that changed or needs action. Attention is a budget, and every pulsing badge spends some of it. Spend it everywhere and it buys nothing.

Most motion that fails review is doing none of these. The rest is usually doing attention while claiming to do feedback. A "Saved" toast that bounces in and wobbles says it is confirming an action, but what it actually does is drag the eye away from whatever the user was working on. That hover lift from the opening was arguably feedback (this card is clickable), except a cursor change and a border colour already did that job for a fraction of the cost. It was a second employee hired to do the first one's work.

Deleting a List Item, Three Ways

Take a hypothetical ten-item task list. The user deletes item four.

Version one: no motion. The row vanishes and rows five to ten jump up instantly. Perception psychology has a name for what goes wrong next: change blindness, the well-documented tendency for people to miss changes that happen during an abrupt swap or disruption. The list after deletion looks much like the list before it. The change is smeared across six rows shifting at once rather than located in one place. Did the delete work? Which item went? The user has to reread the list to find out, which is precisely the work the interface should have done for them.

Version two: gratuitous motion. The row spins, shrinks and bounces off screen. Nobody misses it. But it is slow, it pours attention onto the one item that no longer matters, and charm has a short half-life. On the twentieth deletion of the morning, it is a toll booth.

Version three: purposeful motion. The row fades and its space closes briefly, the siblings slide up into the gap, and an undo affordance appears. Each movement has a job. The fade confirms the action (feedback). The slide shows the list closing ranks, so users can see it is the same list minus one (continuity). The undo offers a way back for the inevitable wrong click. Nothing moves without work to do.

Keep version three in mind. It still has to survive timing, rendering, React and reduced motion.

Duration and Easing Are Grammar, Not Garnish

Speed implies weight and distance. A small toggle that takes as long as a full-screen transition feels sluggish, as if the switch were made of lead. A large panel that snaps into place in an instant feels like a glitch. Duration is how motion tells users how big and how far something is.

Easing implies cause. Objects in the physical world accelerate and decelerate; nothing goes from stationary to full speed and back again in zero time. That is why linear motion feels mechanical, like a lift door. Frank Thomas and Ollie Johnston captured the idea as "slow in and slow out" in The Illusion of Life, their account of the principles Disney's animators worked by, and it transfers to interfaces with very little translation.

In practice, ease-out (fast start, gentle landing) suits elements entering in response to input: the response begins immediately, so it feels connected to the tap, then settles. Ease-in suits elements leaving, gathering speed as they go and releasing the eye. In the list example, the deleted row and its siblings can use different curves because they have different jobs: the row eases in as it departs, and the siblings ease out as they land in the gap.

As for specific numbers, Google's Material Design and Apple's Human Interface Guidelines both publish guidance on motion; check their current versions rather than trusting a duration that has been passed around a team chat for years. What matters more than any single figure is consistency. Define a small set of named durations and curves tied to jobs (something like --motion-feedback, --motion-move, --ease-enter and --ease-exit) so the choice is made once, in one place, instead of being re-argued in every component review.

The Cheap Seats: Transform, Opacity and the Rendering Pipeline

To draw a frame, a browser broadly works through three stages. Layout works out where everything sits and how big it is. Paint fills in the pixels. Composite assembles the painted layers into the final image. Animate top, left, width or height and you can force layout on every frame, and paint after it, which is a lot of work to repeat dozens of times a second. Changes to transform and opacity can usually be handled at the compositing stage, skipping the expensive earlier steps.

That is the basis of web.dev's guidance on high-performance CSS animation: animate transform (translate, rotate, scale) and opacity, and before animating any other property, check what it does to the rendering pipeline. The same guide shows how to verify rather than trust. Move one box by animating top and left, move another with transform: translate, record both in the Chrome DevTools Performance panel and read the Summary. Rendering work showing up for the first box is the layout cost made visible.

The list row's collapsing gap is the awkward case. Shrinking its height is a layout change, and every sibling below it is reflowed on every frame of that collapse. Hold that thought; the next section has the escape hatch.

First, a trap. will-change tells the browser an element is about to change, which can prompt it to promote that element to its own layer. web.dev advises against reaching for it early, because creating layers can cause performance problems of its own. Use it on elements that change constantly, such as a sidebar that slides in and out, or add it with JavaScript just before a change and remove it afterwards. Sprinkling will-change: transform across every card is the CSS equivalent of booking a table at every restaurant in town in case you get hungry.

Animation in React: The Element That Leaves Before It Can Wave

Animation in React has a problem that plain CSS mostly does not. When state says a row is gone, React removes it from the tree, and there is nothing left on screen to animate out. The element has left the building before it could wave goodbye.

Libraries solve this by keeping exiting elements mounted until their exit animation finishes. Motion (formerly Framer Motion) does it with a wrapper component, AnimatePresence, around children that can disappear. The library delays the removal; your state stays honest.

The siblings sliding up are handled by FLIP, a technique popularised by Paul Lewis. First, record where each element is. Apply the change and record where everything ends up: the Last position. Invert, using transforms to put each element back where it started. Then Play, removing the transforms with a transition so everything glides to its new home. Layout happens once; every animated frame is a cheap transform. Many layout animation APIs, including Motion's layout prop, apply this idea under the hood.

FLIP also resolves the height problem. Fade the row out, let it leave the layout in a single step, and let the siblings' transforms close the gap. The collapse is performed by the rows that remain, using properties the compositor handles comfortably.

Whichever tool you use, keep durations, curves and reduced-motion handling in shared components or tokens. Scattering ad-hoc transition props across a codebase is how a team ends up with forty slightly different fades; it is the same argument as keeping behaviour in the component layer rather than in scattered props. Motion provides a useReducedMotion hook for JavaScript-driven animation, and window.matchMedia('(prefers-reduced-motion: reduce)') works without any library. For CSS-driven motion, the media query remains the baseline.

prefers-reduced-motion: Same Job, Different Method

According to MDN, the prefers-reduced-motion media feature detects whether a user has enabled a device setting to minimise non-essential motion: Reduce motion on macOS, the Motion settings on iOS, Remove animations on Android, Animation Effects on Windows 11. That is where people express the preference. Most will never find a toggle buried in your app's settings, so the operating-system signal is the one that counts.

It serves real needs. MDN notes that animations such as scaling or panning large objects can trigger discomfort for people with vestibular motion disorders. The feature takes two values, no-preference and reduce, and @media (prefers-reduced-motion) on its own is equivalent to reduce. MDN lists it as Baseline widely available, across browsers since January 2020.

The most instructive detail is MDN's own example. Under reduce, a scaling pulse does not disappear; it becomes a gentle opacity dissolve. That is the model: reduce or replace the motion, keep the job.

Applied to the list row, the reduced version drops the slide and the travelling siblings. The row crossfades out, the remaining rows settle into place without moving across the screen, and the row that now occupies the slot gets a brief background highlight that fades away. The undo affordance stays. Feedback survives in the fade, and continuity survives in the highlight, which tells the eye exactly where the change happened.

.row-exit {

animation: row-out var(--motion-move) var(--ease-exit) both;

}

@media (prefers-reduced-motion: reduce) {

.row-exit {

animation: fade-out var(--motion-feedback) linear both;

}

.row-settled {

animation: highlight var(--motion-feedback) ease-out;

}

}

Compare the popular blanket override that sets animation: none or near-zero durations on every element whenever reduce matches. It removes the vestibular risk and the useful feedback in one stroke, and hands reduced-motion users version one: rows jumping, nothing confirming the delete, change blindness by design. WCAG 2.3.3 Animation from Interactions, a Level AAA criterion, covers this territory, asking that motion triggered by interaction can be disabled unless it is essential. Meeting it does not require an interface that communicates less.

The Review Test: Name It, Delete It, Reduce It, Profile It

Four questions fit comfortably into a design review or a pull request:

  1. Name it. Which of the four jobs is this motion doing: orientation, continuity, feedback or attention? "It feels nice" is a vibe, and vibes do not appear on job descriptions.
  2. Delete it. Turn the animation off and use the flow for real. If nothing becomes confusing or uncertain, it was decoration.
  3. Reduce it. Design the reduced-motion version. If you cannot say what it should preserve, you never knew the job in the first place.
  4. Profile it. Confirm in DevTools that it animates cheap properties and holds up on a modest device, not just the designer's latest laptop.

The third step does more work than it appears to. Designing the reduced alternative forces a team to separate what a piece of motion communicates from how it moves, and that separation is the job description written out in full. An animation that survives it has earned its place on the page and will survive the next performance audit too. One that does not was always going to be deleted; the reduced-motion version simply gets there first.