Skill Store 33

Framer Motion

Expert knowledge for Framer Motion - the production-ready motion library for React.

by thelobbi · MIT

The skill

Expert knowledge for Framer Motion - the production-ready motion library for React. This skill enables declarative animations, gesture recognition, and layout animations with optimal performance.

Framer Motion Skill

Expert knowledge for Framer Motion - the production-ready motion library for React. This skill enables declarative animations, gesture recognition, and layout animations with optimal performance.

When to Use

Activate this skill when:

  • User mentions "framer motion" or "framer"
  • Working with .tsx or .jsx files containing motion components
  • Need declarative React animations with variants
  • Implementing gesture-driven animations (drag, hover, tap)
  • Building layout animations with layoutId
  • Creating enter/exit animations with AnimatePresence

File Patterns

  • **/*.tsx containing framer-motion imports
  • **/*.jsx containing motion components
  • **/animations/*.ts with variants/transitions
  • **/components/**/use*Animation*.ts

Installation

npm install framer-motion
# or
yarn add framer-motion
# or
pnpm add framer-motion

Core Concepts

Motion Components

Replace HTML elements with motion. prefixed components:

import { motion } from 'framer-motion';

<motion.div
  initial={{ opacity: 0 }}
  animate={{ opacity: 1 }}
  exit={{ opacity: 0 }}
/>

Variants

Define reusable animation states:

const variants = {
  hidden: { opacity: 0, y: 20 },
  visible: { opacity: 1, y: 0 },
};

<motion.div variants={variants} initial="hidden" animate="visible" />

Gestures

Built-in gesture support:

<motion.button
  whileHover={{ scale: 1.1 }}
  whileTap={{ scale: 0.95 }}
  whileFocus={{ outline: '2px solid blue' }}
  whileDrag={{ cursor: 'grabbing' }}
/>

Layout Animations

Automatic layout transitions:

<motion.div layout>
  {/* Content that changes size/position */}
</motion.div>

// Shared element transitions
<motion.div layoutId="shared-element">...</motion.div>

AnimatePresence

Animate components when they mount/unmount:

import { AnimatePresence } from 'framer-motion';

<AnimatePresence mode="wait">
  {isVisible && (
    <motion.div
      key="modal"
      initial={{ opacity: 0 }}
      animate={{ opacity: 1 }}
      exit={{ opacity: 0 }}
    />
  )}
</AnimatePresence>

Animation Properties

Transform Properties

{
  x: 100,           // translateX (pixels)
  y: 100,           // translateY (pixels)
  z: 100,           // translateZ (pixels)
  rotate: 90,       // rotation (degrees)
  rotateX: 90,      // X-axis rotation
  rotateY: 90,      // Y-axis rotation
  scale: 1.5,       // uniform scale
  scaleX: 1.5,      // X-axis scale
  scaleY: 1.5,      // Y-axis scale
  skew: 10,         // skew (degrees)
  originX: 0.5,     // transform origin X (0-1)
  originY: 0.5,     // transform origin Y (0-1)
}

Style Properties

{
  opacity: 0.5,
  backgroundColor: '#ff0000',
  color: '#ffffff',
  borderRadius: 10,
  boxShadow: '0px 10px 30px rgba(0,0,0,0.2)',
  width: 200,
  height: 200,
}

Transition Types

Tween (Default)

transition: {
  type: 'tween',
  duration: 0.3,
  ease: 'easeInOut',
  // Or custom cubic-bezier
  ease: [0.25, 0.1, 0.25, 1],
}

Spring

transition: {
  type: 'spring',
  stiffness: 400,   // Higher = faster
  damping: 30,      // Higher = less bounce
  mass: 1,          // Higher = more momentum
  velocity: 0,      // Initial velocity
}

Inertia (for drag)

transition: {
  type: 'inertia',
  velocity: 50,
  power: 0.8,
  timeConstant: 700,
  bounceStiffness: 500,
  bounceDamping: 10,
}

Common Patterns

Stagger Children

const container = {
  hidden: { opacity: 0 },
  visible: {
    opacity: 1,
    transition: {
      staggerChildren: 0.1,
      delayChildren: 0.2,
    },
  },
};

const item = {
  hidden: { opacity: 0, y: 20 },
  visible: { opacity: 1, y: 0 },
};

<motion.ul variants={container} initial="hidden" animate="visible">
  {items.map(i => (
    <motion.li key={i} variants={item}>{i}</motion.li>
  ))}
</motion.ul>

Orchestrated Animations

const sequence = useAnimation();

async function playSequence() {
  await sequence.start({ x: 100 });
  await sequence.start({ y: 100 });
  await sequence.start({ rotate: 180 });
}

<motion.div animate={sequence} />

Scroll-Linked Animation

import { useScroll, useTransform, motion } from 'framer-motion';

function ParallaxImage() {
  const { scrollYProgress } = useScroll();
  const y = useTransform(scrollYProgress, [0, 1], [0, -200]);

  return <motion.img style={{ y }} />;
}

Drag Constraints

<motion.div
  drag
  dragConstraints={{ left: 0, right: 300, top: 0, bottom: 300 }}
  dragElastic={0.2}
  dragMomentum={false}
  onDragEnd={(e, info) => console.log(info.offset, info.velocity)}
/>

Reduced Motion Support

import { useReducedMotion } from 'framer-motion';

function Component() {
  const shouldReduceMotion = useReducedMotion();

  return (
    <motion.div
      animate={shouldReduceMotion ? { opacity: 1 } : { opacity: 1, y: 0 }}
      initial={shouldReduceMotion ? { opacity: 0 } : { opacity: 0, y: 20 }}
    />
  );
}

Examples

<example> Context: User wants to add a fade-in animation to a card user: "Add a fade-in animation when this card appears" assistant: Wrapping the card with motion.div and adding initial/animate props:

import { motion } from 'framer-motion';

<motion.div
  initial={{ opacity: 0, y: 20 }}
  animate={{ opacity: 1, y: 0 }}
  transition={{ duration: 0.3, ease: 'easeOut' }}
>
  <Card>{content}</Card>
</motion.div>

</example>

<example> Context: User needs a modal with enter/exit animations user: "Make the modal animate when opening and closing" assistant: Using AnimatePresence for mount/unmount animations:

import { AnimatePresence, motion } from 'framer-motion';

<AnimatePresence>
  {isOpen && (
    <motion.div
      key="modal-backdrop"
      initial={{ opacity: 0 }}
      animate={{ opacity: 1 }}
      exit={{ opacity: 0 }}
      className="fixed inset-0 bg-black/50"
    >
      <motion.div
        key="modal-content"
        initial={{ opacity: 0, scale: 0.9, y: 20 }}
        animate={{ opacity: 1, scale: 1, y: 0 }}
        exit={{ opacity: 0, scale: 0.9, y: 20 }}
        transition={{ type: 'spring', damping: 25, stiffness: 300 }}
      >
        {children}
      </motion.div>
    </motion.div>
  )}
</AnimatePresence>

</example>

Related Skills

  • spring-physics - Deep dive into spring animation tuning
  • gsap - Alternative for complex timelines
  • scroll-animations - Advanced scroll-triggered patterns

Resources

Author

Created by Brookside BI as part of React Animation Studio

Use this skill

Connect your agent to the Skill Store MCP server and ask for it by ref: thelobbi/framer-motion-59138625034.

Download SKILL.md · Markdown version

Details

Publisher
thelobbi
Category
Software Development › Frontend & UI
License
MIT
Updated
2026-10-08

References

More from thelobbi