Motion in user interfaces is not decoration. When used well, it guides attention, communicates relationships, and makes interactions feel natural. When used poorly, it annoys users, slows them down, and causes physical discomfort.
Why Motion Matters in UI
Static interfaces force users to mentally track changes. When a sidebar appears instantly, users must figure out what changed. When it slides in, they see the relationship between the trigger and the result.
Motion serves four key purposes:
- Feedback — confirming that an action was received (button press, form submission)
- Orientation — showing where new content came from and where old content went
- Focus — directing attention to what matters right now
- Delight — adding personality that makes an interface feel polished
Disney's 12 Principles, Applied to UI
Disney's animators codified 12 principles of animation in 1981. Several apply directly to interface motion:
Ease In and Ease Out
Objects in the real world do not start and stop instantly. They accelerate and decelerate. The same should apply to UI animations:
/* Bad: linear motion feels robotic */
.panel {
transition: transform 0.3s linear;
}
/* Good: ease-out feels natural for entering elements */
.panel {
transition: transform 0.3s ease-out;
}Common timing functions and when to use them:
| Function | Curve | Best For |
|---|---|---|
ease-out | Fast start, slow end | Elements entering the screen |
ease-in | Slow start, fast end | Elements leaving the screen |
ease-in-out | Slow start and end | Elements moving between positions |
linear | Constant speed | Color changes, opacity fades |
Anticipation
A brief wind-up before the main action tells users something is about to happen:
.button:active {
transform: scale(0.95); /* Slight pull-back before release */
}This subtle scale-down on press creates a sense of physical feedback, like pressing a real button.
Follow-Through
After the main action, elements can overshoot slightly before settling into their final position:
@keyframes pop-in {
0% { transform: scale(0); }
70% { transform: scale(1.05); } /* Overshoot */
100% { transform: scale(1); } /* Settle */
}This makes animations feel bouncy and alive rather than mechanical.
Staging
Direct the user's attention to the most important element. Dim or blur everything else:
/* When a modal opens, fade the background */
.backdrop {
background: rgba(0, 0, 0, 0.5);
backdrop-filter: blur(4px);
transition: opacity 0.2s ease;
}Only one thing should demand attention at a time.
Duration Guidelines
The duration of an animation dramatically affects how it feels:
- 50-100ms — instant feedback (button color change, checkbox toggle)
- 150-300ms — most UI transitions (menus, tooltips, page transitions)
- 300-500ms — complex animations (modals, full-screen transitions)
- 500ms+ — only for decorative or attention-grabbing animations
A general rule: faster is almost always better. Users are here to complete tasks, not watch animations. If a transition feels slow, cut its duration in half.
The prefers-reduced-motion Query
Some users experience motion sickness, vestibular disorders, or seizures triggered by animation. CSS provides a way to respect their preferences:
/* Default: animation plays normally */
.element {
transition: transform 0.3s ease-out;
}
/* User prefers reduced motion: remove or simplify animation */
@media (prefers-reduced-motion: reduce) {
.element {
transition: none;
}
}This is not optional. Respecting prefers-reduced-motion is an accessibility requirement. At minimum, remove parallax effects, auto-playing animations, and large-scale motion. You can replace them with simpler alternatives like opacity fades.
In JavaScript:
const prefersReducedMotion = window.matchMedia(
'(prefers-reduced-motion: reduce)'
).matches;
if (!prefersReducedMotion) {
element.animate([
{ transform: 'translateY(20px)', opacity: 0 },
{ transform: 'translateY(0)', opacity: 1 }
], { duration: 300, easing: 'ease-out' });
}Performance Principles
Smooth animation requires hitting 60 frames per second — that is 16.6ms per frame. Only certain CSS properties can be animated cheaply:
- Cheap (composited) —
transform,opacity— these run on the GPU - Expensive (trigger layout) —
width,height,top,left,margin,padding
Always animate transform and opacity instead of layout properties:
/* Bad: animating top triggers layout recalculation every frame */
.element {
transition: top 0.3s ease;
}
/* Good: animating transform runs on the GPU */
.element {
transition: transform 0.3s ease;
}When Not to Animate
Not everything should move. Skip animation when:
- The user is performing a high-frequency action (typing, scrolling, dragging)
- The content is critical and urgent (error messages, alerts)
- The animation would play on every page load and become annoying
- The animation delays access to content the user is waiting for
Motion should serve the user, not the designer. If you cannot explain why an animation makes the experience better, remove it.