Animations

Framer Motion patterns for delightful interactions.

Hover & Tap Effects

Subtle scale changes provide instant feedback on interactive elements.

Hover me
With rotate
Lift up
<motion.div
  whileHover={{ scale: 1.02 }}
  whileTap={{ scale: 0.98 }}
  transition={{ type: "spring", stiffness: 400, damping: 25 }}
>
  Interactive Element
</motion.div>

Spring Physics

Spring animations feel natural and responsive.

Bouncy (damping: 10)

Balanced (damping: 25)

Snappy (damping: 30)

// Recommended spring settings
transition={{ 
  type: "spring", 
  stiffness: 400, 
  damping: 25 
}}

Stagger Children

Animate lists with staggered delays for a polished feel.

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

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

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

Page Transitions

Smooth entrance animations for page content.

Page Content

Fades in and slides up on mount

<motion.div
  initial={{ opacity: 0, y: 20 }}
  animate={{ opacity: 1, y: 0 }}
  transition={{ duration: 0.3 }}
>
  Page Content
</motion.div>

Layout Animations

Use layout prop for smooth size transitions.

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

// For shared element transitions
<motion.div layoutId="shared-element">
  {/* Will animate between states */}
</motion.div>

Best Practices

Use spring animations

Springs feel more natural than linear or ease timing

Keep animations subtle

Scale between 0.98-1.02 for hover/tap effects

Respect reduced motion

Use useReducedMotion() hook for accessibility

Animate with viewport

Use whileInView with once: true for scroll animations