FR

framer-motion-expert

A guide for implementing declarative animations, layout transitions, and complex UI gestures using Framer Motion.

Install

mkdir -p .claude/skills/framer-motion-expert && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/15548" && unzip -o skill.zip -d .claude/skills/framer-motion-expert && rm skill.zip

Installs to .claude/skills/framer-motion-expert

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Framer Motion 12+ for React. Declarative animations, layout transitions, gestures, scroll-linked motion, AnimatePresence, useAnimate, LazyMotion. Use when building component animations, page transitions, shared layout animations, or gesture-driven UI.
251 chars✓ has a “when” triggerlonger than Claude Code's old 250-char listing cap (fine on current versions)
Intermediate

Key capabilities

  • Implement declarative animations using `motion.div` and other `motion.X` components
  • Orchestrate animations with variants for stagger effects
  • Define various transition types including tween and spring physics
  • Add gesture-driven animations for hover, tap, focus, and drag events
  • Create scroll-triggered animations with `whileInView` and `viewport` options
  • Perform shared layout transitions using the `layout` prop and `layoutId`

How it works

This skill provides patterns for Framer Motion 12+ by detailing core primitives, gestures, layout animations, and hooks for React.

Inputs & outputs

You give it
React component with animation requirements
You get back
Animated React component using Framer Motion

When to use framer-motion-expert

  • Building component animations
  • Creating page transitions
  • Implementing gesture-driven UI
  • Shared layout animations

About this skill

Framer Motion 12+ — Dense Reference

Hallucination Traps (Read First)

  • <Motion> (capital M) → ✅ motion.div (lowercase dot notation)
  • motion() wrapper function → ✅ motion.div, motion.span, etc.
  • exitBeforeEnter prop → ✅ mode="wait" on <AnimatePresence> (removed in FM7+)
  • exit works without <AnimatePresence> → ✅ REQUIRES AnimatePresence wrapper
  • <AnimatePresence> children without unique key → ✅ ALWAYS set key
  • stiffness + damping AND duration + bounce together → ✅ pick ONE pair
  • m.div without <LazyMotion> wrapper → ✅ REQUIRES LazyMotion parent
  • layout animations with domAnimation feature set → ✅ requires domMax
  • ❌ Force-animating width/height/top/left → ✅ use x,y,scale,opacity (GPU)
  • viewport.once defaults to true → ✅ defaults to false — add once: true for entrance anims

Core Primitives

motion.X / Declarative Animation

import { motion } from "framer-motion";
<motion.div
  initial={{ opacity: 0, y: 20 }}
  animate={{ opacity: 1, y: 0 }}
  exit={{ opacity: 0, y: -20 }}
  transition={{ duration: 0.3, ease: "easeOut" }}
/>

Variants (Stagger / Orchestration)

const container = {
  hidden: {},
  visible: { transition: { staggerChildren: 0.08, delayChildren: 0.1 } },
};
const item = {
  hidden: { opacity: 0, y: 20, filter: "blur(4px)" },
  visible: { opacity: 1, y: 0, filter: "blur(0px)", transition: { duration: 0.4 } },
};
<motion.ul variants={container} initial="hidden" animate="visible">
  {list.map(e => <motion.li key={e.id} variants={item}>{e.name}</motion.li>)}
</motion.ul>
// Variant names propagate to children automatically — no need to set initial/animate on each child

Transitions

// Tween (default)
transition={{ duration: 0.5, ease: "easeInOut", delay: 0.2, repeat: Infinity, repeatType: "reverse" }}
// Spring (physics)
transition={{ type: "spring", stiffness: 300, damping: 20 }} // OR use duration+bounce, not both
transition={{ type: "spring", duration: 0.8, bounce: 0.25 }}
// Per-property
transition={{ x: { type: "spring", stiffness: 300 }, opacity: { duration: 0.2 } }}

Gestures

// Hover/Tap/Focus
<motion.button
  whileHover={{ scale: 1.05 }}
  whileTap={{ scale: 0.95 }}
  whileFocus={{ boxShadow: "0 0 0 3px rgba(66,153,225,0.6)" }}
  transition={{ type: "spring", stiffness: 400, damping: 15 }}
/>
// Drag
<motion.div
  drag="x"                                   // "x" | "y" | true
  dragConstraints={{ left: -100, right: 100 }}
  dragElastic={0.2}                          // 0=hard stop, 1=free
  dragMomentum={true}
  dragSnapToOrigin
/>
// Scroll-triggered
<motion.div
  initial={{ opacity: 0, y: 50 }}
  whileInView={{ opacity: 1, y: 0 }}
  viewport={{ once: true, amount: 0.3 }}    // ← once: true is almost always what you want
/>

Layout Animations

// layout prop — auto-animates position/size changes
<motion.div layout transition={{ type: "spring", stiffness: 200 }}>
  {/* layout="position" = only position, layout="size" = only size */}
</motion.div>

// layoutId — shared element transition (morph between renders)
// List thumbnail → expanded modal:
<motion.div key={item.id} layoutId={`card-${item.id}`} />   // in list
<motion.div layoutId={`card-${selectedId}`} className="modal" /> // in modal
// ❌ TRAP: Cross-tree layoutId requires <LayoutGroup> wrapper
import { LayoutGroup } from "framer-motion";
<LayoutGroup><Sidebar /><MainContent /></LayoutGroup>

AnimatePresence

<AnimatePresence mode="sync"> {/* "sync"|"wait"|"popLayout" */}
  {items.map(item => (
    <motion.div key={item.id} /* ← REQUIRED */
      initial={{ opacity: 0, height: 0 }}
      animate={{ opacity: 1, height: "auto" }}
      exit={{ opacity: 0, height: 0 }}
    />
  ))}
</AnimatePresence>
// mode="wait" — waits for exit before entering
// initial={false} on AnimatePresence — skip first-render animation

Scroll Animations

import { useScroll, useTransform } from "framer-motion";
// Page scroll progress (0–1)
const { scrollYProgress } = useScroll();
const y = useTransform(scrollYProgress, [0, 1], [0, -200]);
const opacity = useTransform(scrollYProgress, [0, 0.5], [1, 0]);
<motion.div style={{ y, opacity }} />

// Element-scoped scroll
const ref = useRef(null);
const { scrollYProgress } = useScroll({ target: ref, offset: ["start end", "end start"] });

Hooks

useAnimate — Imperative sequences

import { useAnimate, stagger } from "framer-motion";
const [scope, animate] = useAnimate(); // ← returns [scope, animate] NOT [ref, controls]
await animate(".item", { opacity: 1 }, { delay: stagger(0.1) });
<div ref={scope}>...</div>

useMotionValue + useTransform — No re-renders

const x = useMotionValue(0);
const rotateY = useTransform(x, [-200, 200], [-45, 45]);
// ✅ useMotionValue does NOT trigger React re-renders — key perf advantage over useState
<motion.div style={{ x, rotateY }} drag="x" />

useSpring / useVelocity

const springX = useSpring(x, { stiffness: 300, damping: 30 });
const xVel = useVelocity(x);
const skewX = useTransform(xVel, [-1000, 0, 1000], [-15, 0, 15]);

Performance & Bundle

// LazyMotion — ~5KB vs ~30KB full bundle
import { LazyMotion, domAnimation, m } from "framer-motion";
// domAnimation ≈ 5KB | domMax ≈ 20KB (needed for layout/drag)
<LazyMotion features={domAnimation}><m.div animate={{ opacity: 1 }} /></LazyMotion>

Accessibility

import { useReducedMotion } from "framer-motion";
const reduce = useReducedMotion();
// opacity/color: always safe | position/scale/rotation: must be disabled when reduce=true
<motion.div animate={{ x: reduce ? 0 : 100, opacity: 1 }} transition={{ duration: reduce ? 0 : 0.5 }} />

Rules

  • ✅ Animate: x, y, scale, rotation, opacity (GPU composited)
  • ❌ Never animate: width, height, top, left, padding, margin (causes layout thrashing)
  • useMotionValue for animation-driven values — never useState
  • ❌ Nest AnimatePresence only when necessary — each adds reconciler overhead
  • "use client" required in Next.js — motion.div cannot run in Server Components

When not to use it

  • When using `<Motion>` (capital M) instead of `motion.div`
  • When expecting `exit` animations to work without `<AnimatePresence>`
  • When animating `width`, `height`, `top`, `left`, `padding`, `margin` directly

Limitations

  • This skill does not support `<Motion>` (capital M).
  • This skill requires `<AnimatePresence>` for `exit` animations.
  • This skill does not recommend animating `width`, `height`, `top`, `left`, `padding`, `margin`.

How it compares

This approach focuses on declarative animation patterns and specific Framer Motion features like `AnimatePresence` and `layoutId`, which is more structured than manual CSS animations.

Compared to similar skills

framer-motion-expert side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
framer-motion-expert (this skill)04moNo flagsIntermediate
scroll-experience1016moNo flagsIntermediate
rendering-animate-svg137moNo flagsBeginner
frontend-ui-dark-ts43moReviewIntermediate

Try saying

Example prompts that trigger this skill in your AI assistant.

You might also like

scroll-experience

davila7

Expert in building immersive scroll-driven experiences - parallax storytelling, scroll animations, interactive narratives, and cinematic web experiences. Like NY Times interactives, Apple product pages, and award-winning web experiences. Makes websites feel like experiences, not just pages. Use when: scroll animation, parallax, scroll storytelling, interactive story, cinematic website.

101142

rendering-animate-svg

TheOrcDev

Wrap animated SVG elements in a div to enable hardware acceleration. Apply when animating SVG icons or elements, especially in 8-bit retro components with pixel art animations.

1348

frontend-ui-dark-ts

microsoft

Build dark-themed React applications using Tailwind CSS with custom theming, glassmorphism effects, and Framer Motion animations. Use when creating dashboards, admin panels, or data-rich interfaces with a refined dark aesthetic.

430

react-native-r3f

TheMystic07

Expert guidance for React Three Fiber development with React, Vite, Tailwind CSS, and three.js

00

anthropic-frontend-design

chaibuilder

Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts, posters, or applications (examples include websites, landing pages, dashboards, React components, HTML/CSS layouts, or when styling/beautifying any web UI). Generates creative, polished code and UI design that avoids generic AI aesthetics.

1237

infographic-structure-creator

antvis

Generate or update infographic Structure components for this repo (TypeScript/TSX in src/designs/structures). Use when asked to design, implement, or modify structure layouts (list/compare/sequence/hierarchy/relation/geo/chart), including layout logic, component composition, and registration.

110

Search skills

Search the agent skills registry