| name | motion-design |
| description | This skill should be used when the user wants to add animations, transitions, motion, or movement to any UI. Trigger when the user mentions "add animation", "page transitions", "hover effects", "loading states", "scroll effects", "parallax", "spring animation", "shared element transitions", "gesture-driven motion", "SVG animation", "kinetic typography", or "3D depth effects". Also trigger when the user says an interface "feels static", "feels lifeless", "feels janky", "feels too abrupt", "feels slow", or wants it to "feel like Apple", "feel like iOS", "feel like Vercel", "feel like Linear", "feel smooth", or "feel polished". Use this skill whenever motion is anywhere in the conversation — motion is a design system, not a feature. |
Motion Design for UI
Motion is not decoration. Every animation must earn its place by doing at least one of four jobs: Orientation, Feedback, Status, or Delight. If you cannot name the job, cut the animation.
The Four Jobs of Motion
Before animating anything, identify which job the motion is doing:
- Orientation — Helps the user understand where they are, where they came from, or where they're going. (Page transitions, drawer slides, tab switching)
- Feedback — Confirms that an action was received. (Button press, form submit, toggle, drag confirmation)
- Status — Communicates that something is happening. (Loading, processing, syncing, progress)
- Delight — Creates emotional resonance or personality. (Satisfying completions, expressive reveals, brand moments)
A single animation can serve multiple jobs. If it serves zero, remove it.
Duration Scale
Duration is a system, not a per-animation guess. Use these tiers consistently:
| Tier | Duration | Use Cases |
|---|
| Micro | 80–150ms | Hovers, clicks, toggles, immediate feedback |
| Standard | 200–300ms | Modal opens, panel slides, card expands, tab switches |
| Emphasis | 350–500ms | Page transitions, sheet presentations, structural layout changes |
| Narrative | 500–800ms | Celebrations, first-launch animations, hero reveals |
| Cinematic | 800ms+ | Marketing/editorial only — never in product UI |
Duration expresses hierarchy: elements that matter more take slightly longer.
GPU-Safe Properties — The Cardinal Rule
Always animate these (GPU composited, zero layout cost):
transform: translate() — position
transform: scale() — size
transform: rotate() — rotation
opacity — transparency
filter: blur() — blur (test on mobile)
Never animate these (triggers layout recalculation or paint):
width, height, top, left, right, bottom — use transform: translate/scale() instead
margin, padding, border-width, font-size — full layout recalc
box-shadow — use a pseudo-element with opacity instead
background-color — acceptable at low frequency; avoid during scroll
This is the single most important technical rule. Violating it produces jank that no design quality can recover.
Easing Palette
| Easing | Use Case |
|---|
ease-out cubic-bezier(0.0, 0.0, 0.58, 1.0) | Elements entering the screen — most common |
ease-in cubic-bezier(0.42, 0.0, 1.0, 1.0) | Elements leaving — purposeful departure |
ease-in-out cubic-bezier(0.42, 0.0, 0.58, 1.0) | Transformations that start and end on screen |
Apple enter cubic-bezier(0.0, 0.0, 0.2, 1.0) | Fast, confident iOS-grade entry |
Apple exit cubic-bezier(0.4, 0.0, 1.0, 1.0) | Sharp, decisive iOS-grade exit |
| Spring | Gesture responses, drag, anything velocity-driven |
linear | Progress bars, countdowns, value scrubbing only |
Never use linear for organic motion. Never use transition: all — it animates unintended properties.
For the complete easing catalog with 30+ named curves, see references/easing-catalog.md.
Spring Physics
Springs feel organic because they respond to velocity, not a fixed time curve. Use springs for:
- Gestures and drag interactions (the spring continues at gesture velocity on release)
- Anything that should feel "physical" or "native"
- Interactive elements that need to feel alive on touch
Use Bezier curves for:
- Enter/exit animations, loading sequences — anything time-based and non-interactive
Framer Motion spring presets:
{ type: "spring", stiffness: 400, damping: 40 }
{ type: "spring", stiffness: 500, damping: 50 }
{ type: "spring", stiffness: 200, damping: 15 }
{ type: "spring", stiffness: 280, damping: 60 }
For mathematical depth on spring physics, see references/spring-physics.md.
Common Animation Patterns
Entrance Animations
Always combine translate + opacity. Pure opacity fades look flat.
@keyframes enterUp {
from { opacity: 0; transform: translateY(12px); }
to { opacity: 1; transform: translateY(0); }
}
Direction must be logical: a drawer from the left enters from the left. A tooltip from a button enters toward the user's gaze from the button position.
Exit Animations
Exits are the most neglected part of motion design. Exit toward the logical destination. Duration should be ~80% of entrance duration. Use ease-in for exits (starts slow, peels away).
Shared Element Transitions
When a card expands into a detail view, the card should appear to become the detail view.
<motion.div layoutId="card-1">...</motion.div>
document.startViewTransition(() => updateDOM());
Button & Interactive Feedback
Every interactive element must give immediate physical feedback:
- Hover:
translateY(-1px) or brightness shift, 100–120ms ease-out
- Press/Active:
scale(0.97) + darken, 60–80ms — must feel immediate
- Disabled: No animation — motion implies interactivity
Loading States
- Skeleton screens — always preferred over spinners when content shape is known
- Skeleton pulse:
opacity: 0.4 → 1 → 0.4, 1.5s ease-in-out infinite, with ~150ms stagger across elements
- Spinner — only for unknown-duration async tasks
- Progress bar — most reassuring; use when duration is estimable
Error & Validation
@keyframes errorShake {
0% { transform: translateX(0); }
15% { transform: translateX(-8px); }
30% { transform: translateX(8px); }
45% { transform: translateX(-6px); }
60% { transform: translateX(6px); }
75% { transform: translateX(-4px); }
90% { transform: translateX(4px); }
100% { transform: translateX(0); }
}
Color alone is never sufficient — motion, icons, and text must co-communicate errors for accessibility.
Choreography
When multiple elements animate:
- Stagger by 30–60ms — creates a readable wave, not a simultaneous flash
- Lead with the most important element — first mover gets the eye
- Max 2–3 focal points per interaction — every additional animated element costs cognitive load
- Exits should mirror entrances — optionally slightly faster
const tl = gsap.timeline({ defaults: { ease: "power2.out" } });
tl.from(".hero-headline", { y: 30, opacity: 0, duration: 0.6 })
.from(".hero-subhead", { y: 20, opacity: 0, duration: 0.5 }, "-=0.3")
.from(".hero-cta", { y: 15, opacity: 0, duration: 0.4 }, "-=0.2");
Motion System Tokens
Build a motion system, not a collection of individual decisions:
:root {
--duration-micro: 120ms;
--duration-standard: 240ms;
--duration-emphasis: 360ms;
--duration-narrative: 600ms;
--ease-enter: cubic-bezier(0.0, 0.0, 0.2, 1.0);
--ease-exit: cubic-bezier(0.4, 0.0, 1.0, 1.0);
--ease-both: cubic-bezier(0.4, 0.0, 0.2, 1.0);
--ease-linear: linear;
}
The system test: can a new engineer implement a new animation without asking a designer, and have it feel consistent? If yes, there is a motion system.
Product Personality and Motion
| Product type | Motion character | Key parameters |
|---|
| Finance / Medical / Legal | Precise, restrained | Micro durations, zero overshoot |
| Consumer / Social | Warm, expressive | Low-damping springs, slight bounce |
| Developer Tools | Snappy, functional | Short durations, minimal easing |
| Apple / iOS | Crisp springs, hardware-aware | Near-critically-damped springs |
| Linear / Vercel | Fast, confident, dark | Short micro durations, clean ease-out |
Reduced Motion — Always
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
In Framer Motion:
const prefersReducedMotion =
window.matchMedia("(prefers-reduced-motion: reduce)").matches;
Reduced motion ≠ no motion. Fading is fine. Instant state changes are fine. Eliminate: large spatial translations, spinning, parallax, rapid movement, and any motion creating a sense of moving through space.
For the full accessibility audit workflow, see the motion-accessibility skill.
Additional Reference Files
references/easing-catalog.md — 30+ named easing curves with bezier values, use cases, and personality notes
references/spring-physics.md — Spring equation, parameter guide, preset personalities, critical damping math
references/performance-engineering.md — Browser rendering pipeline, DevTools profiling, GPU-safe properties deep reference, common fixes
Related Skills
gesture-motion-designer — Generate gesture interactions (swipe, drag, pinch) with spring physics
microinteraction-library — Production-ready loading, error, and feedback animation patterns
framer-advanced-physics — Tune spring parameters for specific feels (iOS, bouncy, snappy)
scroll-animation-builder — Scroll-triggered and scroll-linked animations with performance focus
timeline-choreographer — Multi-element animation sequencing and GSAP timelines
animation-performance-auditor — Diagnose and fix janky animations
motion-accessibility — WCAG + prefers-reduced-motion audit and remediation