Back to elements
ElementMiscFree

Animate on Scroll React component

A wrapper that brings content in as it scrolls into view: fade from any side, zoom, blur, flip or a clip-path wipe, one block at once or each child in turn, once or every time, watching the window or any scroll box.

When to use the Animate on Scroll component

Use Animate on Scroll on landing pages and long-form stories to bring sections, images and card grids in as people reach them, so the page feels alive without moving everything at once.

Keep effects consistent within a page (one or two), keep distances small, and leave body text of long articles static.

Installation

Add the Animate on Scroll component to your project with the shadcn CLI. It lands in components/animate-on-scroll.tsx as plain React + Tailwind CSS source you own and can edit.

Install
Copied!
npx shadcn@latest add https://reactframe.com/r/animate-on-scroll.json

Or copy the source by hand and install its dependencies:

Install
Copied!
npm install motion clsx tailwind-merge

Props

<AnimateOnScroll /> accepts 11 props, all optional.

  • children
    React.ReactNode
  • effect
    "fade-up" | "fade-down" | "fade-left" | "fade-right" | "zoom-in" | "blur-in" | "flip-up" | "clip-up"
    Default: "fade-up"
  • stagger

    Animate each direct child in turn, this many seconds apart (0 = animate as one block).

    number
    Default: 0
  • delay
    number
    Default: 0
  • duration
    number
    Default: 0.7
  • distance

    Distance (px) for the slide effects.

    number
    Default: 32
  • once

    Play only the first time it comes into view.

    boolean
    Default: true
  • amount

    How much must be visible to start (0–1).

    number
    Default: 0.25
  • root

    A scroll box to watch instead of the window.

    React.RefObject<Element | null>
  • as
    "div" | "section" | "ul" | "ol"
    Default: "div"
  • className
    string

FAQ

Does it replay when scrolling back up?
Only if you set once={false}; then it reverses when it leaves the screen and plays again when it returns. By default it plays once.
How do I animate items one by one?
Set stagger to the gap in seconds. Each direct child is wrapped and animated in turn; with as="ul" the wrappers are list items.
Is it bad for accessibility?
Content is in the DOM from the start, and with reduced motion enabled it shows immediately without animating.

More Misc components

Focus Trap
Free
Speed Dial
Free
Icon Swap Toggle
Free
Payment Button
Free
Ripple Click Effect
Free
Scroll Progress Bar
Free