Dev In The Mountain Header
A Developer In The mountains having fun

Motion Animation Guide

Master modern web animations with Motion (formerly Framer Motion)

Interactive ExamplesCopy-Paste CodeProduction Ready

What is Motion?

Motion (formerly Framer Motion) is a production-ready animation library for React that makes creating smooth, performant animations simple and declarative. It's now open source and actively maintained by the Motion Division team.

Declarative

Simple, readable animation syntax

Performant

GPU-accelerated by default

Powerful

Advanced physics and gestures

Getting Started

Installation

Install Motion
# Using npm
npm install framer-motion

# Using pnpm
pnpm add framer-motion

# Using yarn
yarn add framer-motion

Basic Usage

The simplest way to animate is using the motion component withinitial, animate, and transition props.

BasicAnimation.jsx
import { motion } from "framer-motion";

function App() {
  return (
    <motion.div
      initial={{ opacity: 0 }}
      animate={{ opacity: 1 }}
      transition={{ duration: 0.5 }}
    >
      <h1>Hello Motion!</h1>
    </motion.div>
  );
}
Basic Fade In
beginner
basics
A simple fade-in animation on page load

I fade in when the page loads!

Using Variants

Variants allow you to define animation states that can be reused across components and orchestrated with stagger effects.

Variants.jsx
import { motion } from "framer-motion";

const containerVariants = {
  hidden: { opacity: 0, scale: 0.8 },
  visible: {
    opacity: 1,
    scale: 1,
    transition: {
      duration: 0.5,
      when: "beforeChildren",
      staggerChildren: 0.1
    }
  }
};

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

function AnimatedList() {
  return (
    <motion.ul
      variants={containerVariants}
      initial="hidden"
      animate="visible"
    >
      {items.map(item => (
        <motion.li key={item.id} variants={itemVariants}>
          {item.text}
        </motion.li>
      ))}
    </motion.ul>
  );
}

Scroll-Triggered Animations

Scroll animations create engaging experiences by responding to user scrolling. Motion provides powerful hooks like useScroll and whileInViewto create scroll-based animations easily.

Fade In On Scroll
beginner
scroll
Elements fade in when they enter the viewport
Box 1
Box 2
Box 3
FadeInOnScroll.jsx
import { motion } from "framer-motion";

function FadeInOnScroll() {
  return (
    <motion.div
      initial={{ opacity: 0, y: 50 }}
      whileInView={{ opacity: 1, y: 0 }}
      viewport={{ once: true }}
      transition={{ duration: 0.5 }}
    >
      <h2>I fade in when scrolled into view!</h2>
    </motion.div>
  );
}
Parallax Effect
intermediate
scroll
Element moves at different speed than scroll

Scroll to see me transform!

Opacity and scale change based on scroll position

ParallaxElement.jsx
import { motion, useScroll, useTransform } from "framer-motion";

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

  return (
    <motion.div style={{ y }}>
      <h2>I move at a different rate than the scroll!</h2>
    </motion.div>
  );
}
Scroll Progress Indicator
beginner
scroll
Visual indicator of scroll progress through the page

The bar above grows as you scroll down the page

ScrollProgress.jsx
import { motion, useScroll } from "framer-motion";

function ScrollProgress() {
  const { scrollYProgress } = useScroll();

  return (
    <motion.div
      style={{
        position: "fixed",
        top: 0,
        left: 0,
        right: 0,
        height: "5px",
        background: "linear-gradient(to right, #61dafb, #4caf50)",
        scaleX: scrollYProgress,
        transformOrigin: "0%"
      }}
    />
  );
}

Gesture Animations

Motion makes it easy to add interactive gestures like hover, tap, and drag with simple props. These create engaging, responsive user experiences.

Hover Effects
beginner
gestures
Scale and shadow changes on hover

Hover over me! 🎨

HoverCard.jsx
import { motion } from "framer-motion";

function HoverCard() {
  return (
    <motion.div
      whileHover={{
        scale: 1.05,
        boxShadow: "0 10px 30px rgba(0,0,0,0.3)"
      }}
      transition={{ type: "spring", stiffness: 300 }}
    >
      <h3>Hover over me!</h3>
    </motion.div>
  );
}
Tap/Click Feedback
beginner
gestures
Button scales down when clicked for tactile feedback
TapButton.jsx
import { motion } from "framer-motion";

function TapButton() {
  return (
    <motion.button
      whileTap={{ scale: 0.95 }}
      whileHover={{ scale: 1.05 }}
      transition={{ type: "spring", stiffness: 400, damping: 17 }}
    >
      Click Me!
    </motion.button>
  );
}
Drag Gestures
intermediate
gestures
Drag element with constraints and elastic boundaries
Drag me! 🎪

Try dragging the box - it bounces back within constraints

DraggableBox.jsx
import { motion } from "framer-motion";

function DraggableBox() {
  return (
    <motion.div
      drag
      dragConstraints={{ left: -100, right: 100, top: -100, bottom: 100 }}
      dragElastic={0.2}
      whileDrag={{ scale: 1.1, cursor: "grabbing" }}
    >
      Drag me around!
    </motion.div>
  );
}
Combined Gestures
intermediate
gestures
Multiple gesture effects on one element
Hover, Click & Drag! 🎭
Try all gestures

Layout & Exit Animations

AnimatePresence enables exit animations and layout prop automatically animates layout changes. Perfect for modals, lists, and dynamic UIs.

Modal with AnimatePresence
intermediate
layout
Smooth enter and exit animations for modal dialogs
Modal.jsx
import { motion, AnimatePresence } from "framer-motion";

function Modal({ isOpen, onClose }) {
  return (
    <AnimatePresence>
      {isOpen && (
        <>
          <motion.div
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            exit={{ opacity: 0 }}
            className="backdrop"
            onClick={onClose}
          />
          <motion.div
            initial={{ opacity: 0, scale: 0.8, y: -50 }}
            animate={{ opacity: 1, scale: 1, y: 0 }}
            exit={{ opacity: 0, scale: 0.8, y: -50 }}
            className="modal"
          >
            <h2>Modal Content</h2>
            <button onClick={onClose}>Close</button>
          </motion.div>
        </>
      )}
    </AnimatePresence>
  );
}
Animated Tab Switching
intermediate
layout
Smooth transitions between tab content with shared element animation

Content for TAB1

This content smoothly transitions when switching tabs.

Tabs.jsx
import { motion } from "framer-motion";

function Tabs() {
  const [selected, setSelected] = useState("tab1");

  return (
    <div>
      <div className="tabs">
        {["tab1", "tab2", "tab3"].map((tab) => (
          <button key={tab} onClick={() => setSelected(tab)}>
            {tab}
            {selected === tab && (
              <motion.div
                layoutId="activeTab"
                className="activeIndicator"
              />
            )}
          </button>
        ))}
      </div>
      <AnimatePresence mode="wait">
        <motion.div
          key={selected}
          initial={{ opacity: 0, x: 20 }}
          animate={{ opacity: 1, x: 0 }}
          exit={{ opacity: 0, x: -20 }}
        >
          {/* Tab content */}
        </motion.div>
      </AnimatePresence>
    </div>
  );
}
Animated List (Add/Remove)
intermediate
layout
Items smoothly animate in and out with layout prop for reordering
Item 1
Item 2
Item 3
Item 4
Item 5
AnimatedList.jsx
import { motion, AnimatePresence } from "framer-motion";

function AnimatedList({ items, onRemove }) {
  return (
    <AnimatePresence>
      {items.map((item) => (
        <motion.div
          key={item.id}
          layout
          initial={{ opacity: 0, scale: 0.8 }}
          animate={{ opacity: 1, scale: 1 }}
          exit={{ opacity: 0, scale: 0.8 }}
          transition={{ type: "spring", stiffness: 300, damping: 25 }}
        >
          {item.content}
          <button onClick={() => onRemove(item.id)}>Remove</button>
        </motion.div>
      ))}
    </AnimatePresence>
  );
}

Spring Physics Playground

Spring animations feel more natural than traditional easing curves. Experiment with the physics parameters to understand how they affect motion.

Interactive Spring Physics
intermediate
physics
Adjust parameters and see how they affect the animation

Presets:

90

How quickly the spring tries to reach its target

7

How much resistance slows down the spring

0.75

The weight of the animated element

Preview:

Hover Me!
SpringAnimation.jsx
import { motion } from "framer-motion";

function SpringAnimation() {
  return (
    <motion.div
      initial={{ rotateY: 0 }}
      animate={{ rotateY: 360 }}
      transition={{
        type: "spring",
        stiffness: 90,
        damping: 7,
        mass: 0.75
      }}
    >
      Animated Element
    </motion.div>
  );
}

Understanding Spring Physics

🎯 Stiffness

Controls how forcefully the spring moves toward its target. Higher values create faster, more energetic animations. Lower values result in slower, more gradual motion.

Range: 1-400 (typical: 100-300)

🛑 Damping

Determines how quickly the spring settles. Higher damping reduces oscillation and makes the animation settle faster. Lower values create more bounce.

Range: 1-50 (typical: 10-30)

⚖️ Mass

Represents the weight or inertia of the element. Heavier objects (higher mass) take longer to accelerate and decelerate, creating a sense of physical presence.

Range: 0.1-5 (typical: 0.5-2)

Resources & Further Learning

Best Practices

Use layout prop for automatic layout animations
Respect prefers-reduced-motion for accessibility
GPU-accelerate with transform and opacity when possible
Use AnimatePresence for exit animations
Leverage spring physics for natural motion

When NOT to Use Motion

Simple CSS transitions are often sufficient
Extremely performance-critical animations
SVG path animations (consider GSAP or CSS)
Timeline-based complex sequences (GSAP might be better)

This page uses Motion v11+ with modern React practices. All code examples are production-ready and tested. Found this helpful? Share it with other developers!

More places to find me
Mental Health
follow me on Mastodon