Parallax photo

A full-bleed photo the page scrolls over: the frame moves while the picture stays nearly still.

Behaviour

  • The photo slides from -100% to +100% of the frame's height, linearly, while the frame crosses the screen from entering at the bottom to leaving at the top, so the picture stays nearly still and the page scrolls over it.
  • Only a transform moves, written straight to the element by motion (no React render per frame); the frame keeps its size, so nothing shifts.
  • The photo starts in place in the server HTML and takes its scroll position once scrolling is measured, so a cover at the top of the page never flashes empty before hydration.
  • Reduced motion: no slide; the photo sits still in its frame.

Props

PropTypeDescription
srcstringThe photo.
altstringDescribe the photo, or "" when it is decoration.
aspectCSSProperties["aspectRatio"]default "16 / 10"The frame's aspect ratio, set inline, so an aspect-* class in className does not override it; a height or min-height in className wins over it.
containerRefObject<HTMLElement | null>Follow a scrolling box instead of the page.
classNamestringMerged onto the frame: size, rounding, a fallback background.

Installation

npx shadcn@latest add https://purrfectui.com/r/parallax-photo.json

How to use

import { ParallaxPhoto } from "@/components/ui/parallax-photo";

<ParallaxPhoto src="/cover.jpg" alt="The venue at night" className="min-h-[60vh]" aspect="16 / 9" />

// inside a scrolling box: follow its scroll instead of the page
const box = useRef<HTMLDivElement>(null);
<div ref={box} className="h-96 overflow-y-auto">
  <ParallaxPhoto src="/cover.jpg" alt="" container={box} />
</div>

Source code

Loading…

Credits

Ported from mapinly.vaibhavtomar.com.

License

MIT. Copy it into your project and change it as you like.

0