framer-motion

v2026.09.24

Framer Motion animation library for React. Declarative, physics-based and gesture-aware: variants and orchestration, AnimatePresence, FLIP layout animation, scroll-linked motion, spring configuration and gestures. USE WHEN: user mentions "Framer Motion", "motion.div", "AnimatePresence", "variants", "layout animation", "spring animation", asks about animating a React component, exit animations, drag or gesture handling DO NOT USE FOR: timeline-based or non-React animation (use `gsap`), SVG-specific animation (use `svg-animation`), pure CSS effects (use `advanced-css-effects`)

GitHub
安装命令
npx skhub add claude-dev-suite/framer-motion
Markdown
SKILL.md

Framer Motion Skill

Animation library for React. Declarative, physics-based, gesture-aware.

Install

npm install framer-motion

Core API

APIPurpose
motion.divAnimatable element
animate propTarget state
initial propStarting state
exit propUnmount state (requires AnimatePresence)
variantsNamed animation states, enables orchestration
transitionTiming, easing, spring config
whileHover / whileTap / whileFocusGesture states
dragDrag gesture with constraints
layout / layoutIdFLIP layout animation
AnimatePresenceAnimates unmounting components
useScrollScroll progress values
useTransformMap one motion value to another
useSpringSpring-based motion value
useInViewObserve element entering viewport
useAnimationImperative animation control

Variants & Orchestration

const container = {
  hidden: {},
  visible: { transition: { staggerChildren: 0.08, delayChildren: 0.1 } }
};
const item = {
  hidden: { opacity: 0, y: 24 },
  visible: { opacity: 1, y: 0, transition: { duration: 0.4, ease: "easeOut" } }
};

<motion.ul variants={container} initial="hidden" whileInView="visible" viewport={{ once: true }}>
  {items.map(i => <motion.li key={i} variants={item}>{i}</motion.li>)}
</motion.ul>

AnimatePresence

<AnimatePresence mode="wait">
  {isVisible && (
    <motion.div
      key="unique-key"
      initial={{ opacity: 0, y: 10 }}
      animate={{ opacity: 1, y: 0 }}
      exit={{ opacity: 0, y: -10 }}
      transition={{ duration: 0.2 }}
    />
  )}
</AnimatePresence>

mode="wait" — exits finish before new element enters. mode="popLayout" — exiting element pops out of layout flow.

Layout Animation (FLIP)

// Automatic smooth repositioning
<motion.div layout />

// Shared element transition across routes/conditions
<motion.div layoutId="card-thumbnail" />  // source
<motion.div layoutId="card-thumbnail" />  // destination — auto-animates

Scroll-linked

const { scrollYProgress } = useScroll({ target: ref, offset: ["start end", "end start"] });
const y = useTransform(scrollYProgress, [0, 1], [0, -100]);
const opacity = useTransform(scrollYProgress, [0, 0.3, 1], [0, 1, 0]);

Spring Config

// Bouncy entrance
transition={{ type: "spring", stiffness: 400, damping: 20 }

// Gentle
transition={{ type: "spring", stiffness: 100, damping: 30 }

// No bounce
transition={{ type: "spring", stiffness: 300, damping: 50 }

Gestures

<motion.button
  whileHover={{ scale: 1.05 }}
  whileTap={{ scale: 0.97 }}
  transition={{ type: "spring", stiffness: 400, damping: 20 }}
>
  Click me
</motion.button>

// Drag with constraints
<motion.div
  drag
  dragConstraints={{ left: -100, right: 100, top: -50, bottom: 50 }}
  dragElastic={0.2}
/>

Imperative Control

const controls = useAnimation();

await controls.start({ opacity: 1, y: 0, transition: { duration: 0.4 } });
controls.stop();

<motion.div animate={controls} initial={{ opacity: 0, y: 20 }} />

Reduced Motion

import { useReducedMotion } from "framer-motion";

function AnimatedCard() {
  const reduced = useReducedMotion();
  return (
    <motion.div
      initial={{ opacity: 0, y: reduced ? 0 : 20 }}
      animate={{ opacity: 1, y: 0 }}
    />
  );
}

Common Patterns

// Stagger list reveal on scroll
// Page transition wrapper
// Accordion with layout animation
// Drag-and-drop with layoutId
// Hero → detail shared element

Pitfalls

  • exit only works inside <AnimatePresence> — wrap the closest conditional parent
  • layout on elements that change children count can cause jumps — use layoutId instead
  • Spring animations ignore duration — use stiffness/damping
  • useScroll without target tracks window scroll
  • Always set viewport={{ once: true }} for entry animations to avoid re-triggering on scroll-up
发现
标签

此技能尚未发布标签。

版本
最新版本元数据

版本

v2026.09.24

发布时间

Sep 24, 2026

分类

未分类

许可证

MIT

源路径

skills/animation/framer-motion

默认分支

main

最新提交

9496306

Tree SHA

fe4e2f1