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
| Prop | Type | Description |
|---|---|---|
| src | string | The photo. |
| alt | string | Describe the photo, or "" when it is decoration. |
| aspect | CSSProperties["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. |
| container | RefObject<HTMLElement | null> | Follow a scrolling box instead of the page. |
| className | string | Merged onto the frame: size, rounding, a fallback background. |
Installation
npx shadcn@latest add https://purrfectui.com/r/parallax-photo.jsonHow 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.