Framer motion
Skill ComeOnOliver/skillshub/skills/aiskillstore/marketplace/asmayaseen/framer-motion
🧠The right skill, one API call. AI agent skills registry with token-efficient skill resolution. 5,000+ skills from 500+ top repos.
npx -y skills add ComeOnOliver/skillshub --skill framer-motionAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
What its author says it does
Copied from the file, not written here
Comprehensive Framer Motion animation library for React. Covers motion components, variants, gestures, page transitions, and scroll animations. Use when adding animations to React/Next.js applications.
SKILL.md
6.5 KB, as published. Nobody here has run it
Framer Motion Skill
Production-ready animations for React applications.
Quick Start
Installation
npm install framer-motion
# or
pnpm add framer-motion
Basic Usage
import { motion } from "framer-motion";
// Simple animation
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 0.5 }}
>
Content
</motion.div>
Core Concepts
| Concept | Guide |
|---|---|
| Motion Component | reference/motion-component.md |
| Variants | reference/variants.md |
| Gestures | reference/gestures.md |
| Hooks | reference/hooks.md |
Examples
| Pattern | Guide |
|---|---|
| Page Transitions | examples/page-transitions.md |
| List Animations | examples/list-animations.md |
| Scroll Animations | examples/scroll-animations.md |
| Micro-interactions | examples/micro-interactions.md |
Templates
| Template | Purpose |
|---|---|
| templates/page-transition.tsx | Page transition wrapper |
| templates/animated-list.tsx | Animated list component |
Quick Reference
Basic Animation
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -20 }}
transition={{ duration: 0.3 }}
>
Content
</motion.div>
Hover & Tap
<motion.button
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
transition={{ type: "spring", stiffness: 400, damping: 17 }}
>
Click me
</motion.button>
Variants
const container = {
hidden: { opacity: 0 },
show: {
opacity: 1,
transition: { staggerChildren: 0.1 }
}
};
const item = {
hidden: { opacity: 0, y: 20 },
show: { opacity: 1, y: 0 }
};
<motion.ul variants={container} initial="hidden" animate="show">
{items.map(i => (
<motion.li key={i} variants={item}>{i}</motion.li>
))}
</motion.ul>
AnimatePresence (Exit Animations)
import { AnimatePresence, motion } from "framer-motion";
<AnimatePresence mode="wait">
{isVisible && (
<motion.div
key="modal"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
>
Modal content
</motion.div>
)}
</AnimatePresence>
Scroll Trigger
<motion.div
initial={{ opacity: 0, y: 50 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, margin: "-100px" }}
transition={{ duration: 0.5 }}
>
Animates when scrolled into view
</motion.div>
Drag
<motion.div
drag
dragConstraints={{ left: -100, right: 100, top: -100, bottom: 100 }}
dragElastic={0.1}
>
Drag me
</motion.div>
Layout Animation
<motion.div layout layoutId="shared-element">
Content that animates when layout changes
</motion.div>
Transition Types
// Tween (default)
transition={{ duration: 0.3, ease: "easeOut" }}
// Spring
transition={{ type: "spring", stiffness: 300, damping: 20 }}
// Spring presets
transition={{ type: "spring", bounce: 0.25 }}
// Inertia (for drag)
transition={{ type: "inertia", velocity: 50 }}
Easing Functions
// Built-in easings
ease: "linear"
ease: "easeIn"
ease: "easeOut"
ease: "easeInOut"
ease: "circIn"
ease: "circOut"
ease: "circInOut"
ease: "backIn"
ease: "backOut"
ease: "backInOut"
// Custom cubic-bezier
ease: [0.17, 0.67, 0.83, 0.67]
Reduced Motion
Always respect user preferences:
import { motion, useReducedMotion } from "framer-motion";
function Component() {
const prefersReducedMotion = useReducedMotion();
return (
<motion.div
initial={{ opacity: 0, y: prefersReducedMotion ? 0 : 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: prefersReducedMotion ? 0 : 0.3 }}
>
Respects motion preferences
</motion.div>
);
}
// Or use media query
const variants = {
initial: { opacity: 0 },
animate: { opacity: 1 },
};
<motion.div
variants={variants}
initial="initial"
animate="animate"
className="motion-reduce:transition-none"
>
Common Patterns
Fade In Up
const fadeInUp = {
initial: { opacity: 0, y: 20 },
animate: { opacity: 1, y: 0 },
transition: { duration: 0.4 }
};
<motion.div {...fadeInUp}>Content</motion.div>
Staggered List
const container = {
hidden: { opacity: 0 },
show: {
opacity: 1,
transition: { staggerChildren: 0.1, delayChildren: 0.2 }
}
};
const item = {
hidden: { opacity: 0, x: -20 },
show: { opacity: 1, x: 0 }
};
Modal
<AnimatePresence>
{isOpen && (
<>
{/* Backdrop */}
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
className="fixed inset-0 bg-black/50"
onClick={onClose}
/>
{/* Modal */}
<motion.div
initial={{ opacity: 0, scale: 0.95 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.95 }}
className="fixed inset-x-4 top-1/2 -translate-y-1/2 ..."
>
Modal content
</motion.div>
</>
)}
</AnimatePresence>
Accordion
<motion.div
initial={false}
animate={{ height: isOpen ? "auto" : 0 }}
transition={{ duration: 0.3, ease: "easeInOut" }}
className="overflow-hidden"
>
<div className="p-4">Accordion content</div>
</motion.div>
Best Practices
- Use variants: Cleaner code, easier orchestration
- Respect reduced motion: Always check
useReducedMotion - Use
layoutsparingly: Can be expensive, use only when needed - Exit animations: Wrap with
AnimatePresence - Spring for interactions: More natural feel for hover/tap
- Tween for page transitions: More predictable timing
- GPU-accelerated properties: Prefer
opacity,scale,x,yoverwidth,height