| license | Apache-2.0 |
| name | motion-design-web |
| description | Motion design and micro-animations for web interfaces — Framer Motion layout animations, CSS scroll-driven animations, View Transitions API, GSAP ScrollTrigger, spring physics tuning, loading choreography, and Disney's 12 principles applied to UI. Makes interfaces feel alive without feeling busy. Activate on 'web animation', 'Framer Motion', 'micro-interaction', 'scroll animation', 'page transition', 'View Transitions API', 'spring animation web', 'motion design', 'loading animation', 'skeleton screen', 'hover effect', 'GSAP ScrollTrigger'. |
| allowed-tools | Read,Write,Edit,Glob,Grep,WebSearch,WebFetch |
| metadata | {"category":"Design & UX","tags":["animation","motion-design","framer-motion","css-animations","gsap","micro-interactions","page-transitions","scroll-driven"],"pairs-with":[{"skill":"react-performance-optimizer","reason":"Animations must not compromise render performance"},{"skill":"web-design-expert","reason":"Motion serves the visual design, not the other way around"},{"skill":"hero-section-design","reason":"Hero sections rely heavily on entrance animations and scroll effects"},{"skill":"native-app-designer","reason":"Shared principles of spring physics and interaction feedback"}]} |
| category | Design & Creative |
| tags | ["motion-design","animation","web","transitions","ux"] |
Motion Design for Web
Motion is the invisible layer between good design and great design. When done right, users don't notice the animations — they notice the app feels responsive, alive, intentional. When done wrong, they notice that something is bouncing and they wish it would stop.
Decision Points
Library Selection by Complexity/Performance
Project Requirements → Library Choice
├── Simple transitions (hover, fade, slide)?
│ └── Use CSS transitions/animations
│ - Low bundle size impact
│ - Hardware accelerated
│ - Good enough for 80% of needs
├── Layout animations, gesture handling, or complex sequences?
│ ├── React project?
│ │ └── Use Framer Motion
│ │ - Layout animations automatic
│ │ - AnimatePresence for mount/unmount
│ │ - Spring physics built-in
│ └── Vanilla JS or non-React?
│ └── Use GSAP
│ - Maximum control and performance
│ - ScrollTrigger for scroll effects
│ - Complex timeline orchestration
├── Scroll-driven effects only?
│ ├── Browser support modern (Chrome 115+)?
│ │ └── Use CSS scroll-driven animations
│ │ - Zero JavaScript overhead
│ │ - Runs off main thread
│ └── Need older browser support?
│ └── Use GSAP ScrollTrigger
└── Cross-page transitions?
├── Shared elements between pages?
│ └── Use View Transitions API
│ - Browser handles morphing automatically
│ - Fallback to regular page load
└── Simple page-level effects?
└── CSS animations with navigation events
Timing Decision Tree
Animation Purpose → Duration Range
├── Instant feedback (hover acknowledgment)?
│ └── 100-150ms with ease-out
├── State change confirmation (toggle, selection)?
│ └── 200-250ms with ease-in-out
├── Content reveal (dropdown, accordion)?
│ └── 300-400ms with spring physics
├── Major context change (modal, page)?
│ └── 400-600ms with anticipation + follow-through
└── Background activity (loading, progress)?
└── 1.5-2s cycle or tied to actual progress
Spring Physics Tuning
Interaction Type → Spring Config
├── Snappy UI controls (buttons, switches)?
│ └── stiffness: 400, damping: 28
├── Smooth panels (modals, cards)?
│ └── stiffness: 200, damping: 24
├── Playful elements (success animations)?
│ └── stiffness: 300, damping: 15 (more bounce)
├── Heavy elements (full-page sheets)?
│ └── stiffness: 120, damping: 20, mass: 1.5
└── Gesture-driven (drag, swipe)?
└── stiffness: 300, damping: 20, velocity inheritance
Failure Modes
Layout Thrashing Jank
Detection: Animation drops below 60fps, DevTools Performance tab shows purple "Layout" blocks during animation
Symptoms: Choppy motion, especially on slower devices; scrolling feels laggy during transitions
Root Cause: Animating properties that trigger layout recalculation (width, height, margin, padding, top, left)
Only animate transform, opacity, filter, clip-path; use transform: scale() instead of width/height changes