Motion

Pointer Parallax

A pointer-driven parallax group where each Parallax Layer eases toward the cursor by its own depth and settles back on leave. Mouse and pen only; holds still under reduced motion.

The source comes with full access.

One payment of $149 ($49 for now) opens the source right here and lets the CLI install every paid component, with lifetime updates.

Installation

pnpm dlx shadcn add @01orbital/pointer-parallax
npx shadcn add @01orbital/pointer-parallax
yarn shadcn add @01orbital/pointer-parallax
bunx --bun shadcn add @01orbital/pointer-parallax

Part of the 01orbital library. With a license, put ORBITAL_TOKEN in .env.local and the same command installs it (licensed install, pricing).

It lands at components/motion/pointer-parallax.tsx, as source you own and edit.

Usage

import {
  ParallaxLayer,
  PointerParallax,
} from "@/components/motion/pointer-parallax"

const IMAGES = [
  "https://01orbital.dev/art/kit/layered-currents-553717.png",
  "https://01orbital.dev/art/kit/layered-currents-193392.png",
  "https://01orbital.dev/art/kit/layered-currents-371122.png",
  "https://01orbital.dev/art/kit/layered-currents-505999.png",
  "https://01orbital.dev/art/kit/layered-currents-693088.png",
  "https://01orbital.dev/art/kit/layered-currents-854231.png",
]

export default function PointerParallaxDemo() {
  return (
    <div className="dark relative isolate grid min-h-96 w-full place-items-center overflow-hidden bg-background text-foreground">
      <PointerParallax sensitivity={-1}>
        {/* Width is the knob; height stays auto so art keeps its own ratio. */}
        <ParallaxLayer depth={0.5} className="top-[12%] left-[12%] w-[18%]">
          <img src={IMAGES[0]} alt="" className="h-auto w-full" />
        </ParallaxLayer>
        <ParallaxLayer depth={1} className="top-[8%] left-[36%] w-[20%]">
          <img src={IMAGES[1]} alt="" className="h-auto w-full" />
        </ParallaxLayer>
        <ParallaxLayer depth={2} className="top-[14%] left-[64%] w-[20%]">
          <img src={IMAGES[2]} alt="" className="h-auto w-full" />
        </ParallaxLayer>
        <ParallaxLayer depth={1} className="top-[58%] left-[18%] w-[20%]">
          <img src={IMAGES[3]} alt="" className="h-auto w-full" />
        </ParallaxLayer>
        <ParallaxLayer depth={3} className="top-[64%] left-[48%] w-[22%]">
          <img src={IMAGES[4]} alt="" className="h-auto w-full" />
        </ParallaxLayer>
        <ParallaxLayer depth={2} className="top-[60%] left-[76%] w-[18%]">
          <img src={IMAGES[5]} alt="" className="h-auto w-full" />
        </ParallaxLayer>
      </PointerParallax>
    </div>
  )
}

Anatomy

Pointer Parallax is built from 2 parts. In the example they nest like this:

PointerParallax
└─ ParallaxLayer
  • PointerParallax: A pointer parallax group. It fills its positioned parent, and each ParallaxLayer inside drifts toward the pointer by its own depth, then eases back to rest when the pointer leaves.
  • ParallaxLayer: One moving piece inside PointerParallax. It is absolutely positioned, so place it with className, and it drifts toward the pointer by depth.

API reference

PointerParallax

A pointer parallax group. It fills its positioned parent, and each ParallaxLayer inside drifts toward the pointer by its own depth, then eases back to rest when the pointer leaves.

It follows a mouse or pen, not touch, and reduced motion keeps every layer at rest. Up to 20 layers move; any past that stay still, so group related pieces under one ParallaxLayer.

Prop

Type

It also accepts the HTML attributes of the element it renders.

ParallaxLayer

One moving piece inside PointerParallax. It is absolutely positioned, so place it with className, and it drifts toward the pointer by depth.

The drift is a translate written before any transform you pass in style, so your own rotate or scale stays. Tailwind's translate-*, rotate-* and scale-* classes use separate properties and keep working too.

Prop

Type

It also accepts the HTML attributes of the element it renders.

Dependencies

npm: cn. The CLI installs them for you.

No other registry pieces.