Skip to main content

Live demo

Slide animations move elements into view from a specific direction, creating a sense of spatial awareness and directionality. They’re perfect for navigation menus, sidebars, and sequential content reveals.
Combine slide animations with fade effects for smoother, more polished transitions.

Complete code example

import { motion } from 'framer-motion'
import { useState } from 'react'

export default function SlideInDemo() {
  const [direction, setDirection] = useState<'left' | 'right' | 'top' | 'bottom'>('left')

  const variants = {
    left: { x: -100, opacity: 0 },
    right: { x: 100, opacity: 0 },
    top: { y: -100, opacity: 0 },
    bottom: { y: 100, opacity: 0 },
  }

  return (
    <div>
      <div className="flex gap-2 mb-4">
        {(['left', 'right', 'top', 'bottom'] as const).map((dir) => (
          <button
            key={dir}
            onClick={() => setDirection(dir)}
            className="px-3 py-1 bg-blue-500 text-white rounded"
          >
            {dir}
          </button>
        ))}
      </div>

      <motion.div
        key={direction}
        initial={variants[direction]}
        animate={{ x: 0, y: 0, opacity: 1 }}
        transition={{ type: 'spring', damping: 25, stiffness: 300 }}
        className="p-6 bg-gradient-to-r from-purple-500 to-pink-500 text-white rounded-lg"
      >
        Sliding from {direction}
      </motion.div>
    </div>
  )
}

How it works

Slide animations use transform properties to move elements:
1

Initial position

Place the element off-screen or offset from its final position using translateX or translateY.
2

Animate to final

Transition the transform to translate(0) to slide the element into its natural position.
3

Add opacity

Combine with opacity changes (0 to 1) for a smoother, more polished effect.

Direction reference

From left

translateX(-100%) or x: -100

From right

translateX(100%) or x: 100

From top

translateY(-100%) or y: -100

From bottom

translateY(100%) or y: 100

Variations

Slide in sidebar

Common pattern for navigation menus:
import { motion, AnimatePresence } from 'framer-motion'

function Sidebar({ isOpen, onClose }) {
  return (
    <AnimatePresence>
      {isOpen && (
        <>
          {/* Backdrop */}
          <motion.div
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            exit={{ opacity: 0 }}
            onClick={onClose}
            className="fixed inset-0 bg-black/50 z-40"
          />
          
          {/* Sidebar */}
          <motion.div
            initial={{ x: -300 }}
            animate={{ x: 0 }}
            exit={{ x: -300 }}
            transition={{ type: 'spring', damping: 30, stiffness: 300 }}
            className="fixed left-0 top-0 bottom-0 w-64 bg-white shadow-xl z-50"
          >
            Sidebar content
          </motion.div>
        </>
      )}
    </AnimatePresence>
  )
}

Sequential slide in

Slide in items one after another:
import { motion } from 'framer-motion'

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

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

function SequentialSlide({ items }) {
  return (
    <motion.div
      variants={container}
      initial="hidden"
      animate="show"
    >
      {items.map((text, i) => (
        <motion.div
          key={i}
          variants={item}
          className="p-4 mb-2 bg-gray-100 rounded"
        >
          {text}
        </motion.div>
      ))}
    </motion.div>
  )
}

Slide and rotate

Add rotation for dynamic effect:
<motion.div
  initial={{ x: -100, opacity: 0, rotate: -10 }}
  animate={{ x: 0, opacity: 1, rotate: 0 }}
  transition={{ type: 'spring', stiffness: 200 }}
>
  Content
</motion.div>

Best practices

Slide direction should match the user’s mental model:
  • Navigation from left for LTR languages
  • Modals from bottom on mobile
  • Notifications from top or corner
Spring-based transitions feel more natural than linear ones for slide animations.
// Good
transition={{ type: 'spring', damping: 25 }}

// Less natural
transition={{ duration: 0.3, ease: 'linear' }}
When sliding in panels or sidebars, include a semi-transparent backdrop.
On mobile, allow users to swipe to dismiss slide-in panels.

Common use cases

  • Navigation drawers and sidebars
  • Mobile menu overlays
  • Notification panels
  • Image carousels
  • Wizard steps
  • Chat messages

Performance tips

Always use transform: translate() instead of left/right/top/bottom for animations. Transform is GPU-accelerated and won’t trigger layout recalculations.
// Good - GPU accelerated
<motion.div animate={{ x: 0 }} />

// Bad - Causes layout thrashing
<motion.div animate={{ left: 0 }} />

Fade in

Opacity-based transitions

Drag gesture

Swipeable interactions

Morph

Shape transformations

Build docs developers (and LLMs) love