Framer Motion: Essential Animation Patterns

Framer Motion makes React animations simple and powerful. Here are the patterns you'll use most.

Setup

npm install framer-motion

Basic Animations

Fade In

import { motion } from 'framer-motion'

export function FadeIn({ children }) {
  return { children }
}

Slide In

export function SlideIn({ children }) {
  return { children }
}

Hover & Tap Interactions

export function AnimatedButton({ children, onClick }) {
  return { children }
}

Variants (Staggered Animations)

const container = {
  hidden: { opacity: 0 },
  show: {
    opacity: 1,
    transition: { staggerChildren: 0.1 }
  }
}

const item = {
  hidden: { opacity: 0, x: -20 },
  show: { opacity: 1, x: 0 }
}

export function StaggeredList({ items }) {
  return (
      {items.map((text, i) => (
          {text}
      ))}

  )
}

Drag and Drop

export function DraggableCard() {
  return (

  )
}

Layout Animations

import { useState } from 'react'

export function ExpandableCard() {
  const [isOpen, setIsOpen] = useState(false)

  return (
    <motion.div
      layout
      onClick={() => setIsOpen(!isOpen)}
      className="bg-white p-6 rounded-lg cursor-pointer"
    >
      Title
      {isOpen && (
          Content appears here
      )}

  )
}

Scroll Animations

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

export function ParallaxSection({ children }) {
  const { scrollYProgress } = useScroll()
  const y = useTransform(scrollYProgress, [0, 1], ['0%', '50%'])

  return { children }
}

Scroll Progress Bar

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

  return (

  )
}

Exit Animations

import { AnimatePresence } from 'framer-motion'

export function Modal({ isOpen, onClose, children }) {
  return (

      {isOpen && (
        <>
              {children}
        </>
      )}

  )
}

Page Transitions

import { usePathname } from 'next/navigation'

const pageVariants = {
  initial: { opacity: 0, x: -20 },
  animate: { opacity: 1, x: 0 },
  exit: { opacity: 0, x: 20 },
}

export function PageTransition({ children }) {
  const pathname = usePathname()

  return { children }
}

Like Button Microinteraction

export function LikeButton() {
  const [liked, setLiked] = useState(false)

  return (
    <motion.button
      onClick={() => setLiked(!liked)}
      whileTap={{ scale: 0.9 }}
    >

  )
}

Performance Tips

  1. Use transform and opacity - hardware accelerated
  2. Avoid animating width/height - use scale instead
  3. Add layout sparingly - can be expensive
  4. Respect prefers-reduced-motion:
const shouldReduceMotion = window.matchMedia(
  '(prefers-reduced-motion: reduce)',
).matches

Learn More: Framer Motion Docs