Get started
Installation
npm install @iampoul/react-parallax- Zero dependencies — Only a React peer dependency required
- Performant — Single rAF loop — layers update via refs, no re-renders
- Accessible — Auto-pauses for prefers-reduced-motion
- Flexible — Scroll, pointer, or both. Per-layer speed, rotate, scale, fade, blur
- TypeScript — Full type definitions included
import { Parallax, ParallaxLayer } from "@iampoul/react-parallax"
export function Scene() {
return (
<Parallax mode="both" intensity={1} smoothing={0.12}>
{/* Background — moves slower, blurs at scroll edges */}
<ParallaxLayer speed={0.5} pointerStrength={20} blur={4}>
<img src="/bg.png" alt="" />
</ParallaxLayer>
{/* Foreground — moves faster, always slightly soft */}
<ParallaxLayer speed={-0.3} pointerStrength={40} blurBase={2} zIndex={1}>
<img src="/fg.png" alt="" />
</ParallaxLayer>
</Parallax>
)
}Examples
Demos
Scroll depth
Layers with different speed values create depth as you scroll. Positive values recede into the background, negative values come forward.
<Parallax mode="scroll" intensity={1} smoothing={0.1}>
{/* Slowest — furthest away */}
<ParallaxLayer speed={0.7} scrollRange={80}>…</ParallaxLayer>
{/* Mid distance */}
<ParallaxLayer speed={0.35} scrollRange={80}>…</ParallaxLayer>
{/* Fastest — closest */}
<ParallaxLayer speed={-0.4} scrollRange={80}>…</ParallaxLayer>
</Parallax>Pointer tilt
pointerStrength controls how far each layer shifts in response to the cursor. Higher values create more dramatic parallax.
<Parallax mode="pointer" intensity={1.2} smoothing={0.07}>
<ParallaxLayer pointerStrength={12}>…</ParallaxLayer>
<ParallaxLayer pointerStrength={28}>…</ParallaxLayer>
<ParallaxLayer pointerStrength={50}>…</ParallaxLayer>
<ParallaxLayer pointerStrength={80}>…</ParallaxLayer>
</Parallax>Rotate, scale & fade
Combine rotate, scale, and fade on layers for richer scroll transitions.
<Parallax mode="scroll" intensity={1} smoothing={0.1}>
<ParallaxLayer speed={0.2} rotate={120} scrollRange={100} />
<ParallaxLayer speed={-0.3} rotate={-80} scale={0.3} scrollRange={100} />
<ParallaxLayer speed={0.5} fade={0.2} scrollRange={100} />
</Parallax>Blur depth-of-fieldv0.2.0
The blur prop applies a dynamic blur() CSS filter — sharp at scroll center, soft toward the edges. Like a camera pulling focus.
<Parallax mode="scroll" intensity={1} smoothing={0.1}>
{/* Far — blurs out at scroll edges */}
<ParallaxLayer speed={0.6} blur={10} scrollRange={90} />
{/* Mid — subtle blur */}
<ParallaxLayer speed={0.25} blur={5} scrollRange={90} />
{/* Near — always sharp */}
<ParallaxLayer speed={-0.3} blur={0} scrollRange={90} />
</Parallax>Always-soft backgroundv0.2.0
blurBase applies a constant blur at all scroll positions — perfect for soft atmospheric backgrounds. Composes with blur: total = blurBase + |scroll| × blur.
<Parallax mode="both" intensity={1} smoothing={0.09}>
{/* Always blurred — constant soft atmosphere */}
<ParallaxLayer speed={0.5} blurBase={5} scrollRange={80} />
{/* Blurred + gets softer toward edges */}
<ParallaxLayer speed={0.2} blurBase={3} blur={4} scrollRange={80} />
{/* Sharp focal point */}
<ParallaxLayer speed={-0.15} scrollRange={80} />
</Parallax>Live playground
Tweak the <Parallax> container props in real time. The code block reflects your current settings.
<Parallax> props
<Parallax
mode="both"
intensity={1.0}
smoothing={0.10}
disabled={false}
>API Reference
Props
<Parallax>
The container element that tracks scroll and pointer movement and broadcasts it to all child layers via a ref-based subscription — no re-renders.
| prop | type | default | description |
|---|---|---|---|
mode | "scroll" | "pointer" | "both" | "both" | Which inputs drive the parallax effect |
intensity | number | 1 | Global movement multiplier — 0.5 subtle, 2 dramatic |
smoothing | number | 0.12 | Easing factor — lower is floatier, 1 is instant |
disabled | boolean | false | Pause all motion. Auto-enabled for prefers-reduced-motion |
as | ElementType | "div" | HTML element to render as the container |
className | string | — | CSS class for the container element |
style | CSSProperties | — | Inline styles for the container element |
<ParallaxLayer>
A single layer inside a container. Drop in as many as needed. Each layer independently controls its depth, motion axis, rotation, scale, and fade.
| prop | type | default | description |
|---|---|---|---|
speed | number | 0.3 | Depth factor — 0 locked, >0 slower/background, <0 faster/foreground |
pointerStrength | number | 0 | Pixels of travel from pointer movement |
scrollRange | number | 120 | Max pixels of scroll travel |
axis | "x" | "y" | "both" | "y" | Which axis scroll parallax applies to |
rotate | number | 0 | Degrees of rotation applied across the scroll range |
scale | number | 0 | Extra scale applied at scroll edges (0.2 = +20%) |
fade | number | 1 | Opacity at scroll edges — 1 means no fade |
blur | number | 0 | Max blur in px at scroll edges, 0px at center — creates a depth-of-field focus effect |
blurBase | number | 0 | Constant blur in px always applied — for layers that should always appear out of focus. Composes with blur |
zIndex | number | 0 | Stacking order for the layer |
as | ElementType | "div" | HTML element to render as the layer |
className | string | — | CSS class for the layer element |
style | CSSProperties | — | Inline styles for the layer element |
useParallax()
Access the parallax context from custom components inside a container.
const { intensity, disabled, mode, subscribe, getState } = useParallax()