Scroll Animation

Reveals that play once when an element scrolls into view, and a parallax layer that drifts with the scroll.

Examples

Presets

Scroll down, one element arrives at a time
fade-up

Every pitch on one map

Traders see where they stand on Saturday, who their neighbours are and whether the pitch is covered.

scale-in
Pitch 14Covered, next to the bakery
Confirmed
clip-reveal

Parallax layer

The night ferry

The ferry to Larkspur Sound leaves the harbour at nine. In summer the deck is full of walkers who finished the coast path that afternoon and want to see it again from the water.

The crossing takes forty minutes. The cliffs pass on the left, then the old signal house, then the long beach where the path began in the morning.

By the time the boat reaches the sound, the light is almost gone. The lamps of the village come on one by one along the quay.

The last bus back to town waits for the ferry. Nobody has ever seen it leave without the walkers on board.

Installation

npx shadcn@latest add https://ui.ndekocode.dev/r/motion-scroll-animation.json

Component API

Wrap one element per reveal and keep them apart, so only one thing moves at a time. With reduced motion, every element is in place from the start and the parallax layer stays still.

ScrollAnimation

PropTypeDefaultDescription
childrenReact.ReactNodeThe element to reveal.
preset'fade-up' | 'scale-in' | 'clip-reveal''fade-up'Rise 16px and fade in, grow from 96% and fade in, or uncover from the bottom edge.
delaynumber0Delay before the reveal, in seconds.
amountnumber0.3The share of the element that must be visible before it plays.
containerRefRefObject<HTMLElement | null>The scrolling element, when it is not the page.
classNamestringundefinedOptional CSS class for the wrapper.

ScrollParallax

A frame that clips a layer, which drifts against the scroll while the frame crosses the view.

PropTypeDefaultDescription
childrenReact.ReactNodeThe content of the layer, usually an image that fills it.
strengthnumber40How far the layer drifts each way, in pixels. A negative value moves it with the scroll instead.
classNamestringundefinedClasses of the frame. Give it a size, for instance an aspect ratio.
layerClassNamestringundefinedClasses of the moving layer.
containerRefRefObject<HTMLElement | null>The scrolling element, when it is not the page. It needs a non-static position.