WebberUI

Parallax Section

A multi-layer parallax section where each layer shifts at a different speed with scroll progress, stacking up depth and a sense of space.

Loading preview…
npx shadcn@latest add https://webberui.com/r/parallax-section.json

Playground

Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.

120
0.5
<ParallaxSection />

Installation

npx shadcn@latest add https://webberui.com/r/parallax-section.json

Or, once registries are configured in components.json, install it as @webberui/parallax-section.

Usage

Use ParallaxSection as the container and put several ParallaxLayer elements inside it. Most parallax layers are stacked with absolute inset-0, and speed decides each layer's displacement multiplier relative to the scroll:

import {
  ParallaxLayer,
  ParallaxSection,
} from "@/components/ui/parallax-section";

<ParallaxSection className="h-[420px] bg-neutral-950">
  {/* Background: sinks slowly */}
  <ParallaxLayer decorative speed={-0.6} className="absolute inset-0">
    <div className="absolute inset-0 bg-gradient-to-b from-indigo-500/30 to-transparent" />
  </ParallaxLayer>

  {/* Foreground: floats up quickly and fades out */}
  <ParallaxLayer
    speed={1.2}
    fade
    className="absolute inset-0 flex items-center justify-center"
  >
    <h2 className="text-4xl font-bold text-white">Multi-layer parallax</h2>
  </ParallaxLayer>
</ParallaxSection>;

Nested scroll container

If the parallax happens inside a fixed-height container that scrolls internally (rather than the whole window), pass that container's ref to container:

const scrollerRef = React.useRef<HTMLDivElement>(null);

<div ref={scrollerRef} className="h-[300px] overflow-y-auto">
  <ParallaxSection container={scrollerRef}>{/* … */}</ParallaxSection>
</div>;

Props

ParallaxSection

PropTypeDefaultDescription
childrenReactNodeOne or more ParallaxLayer elements
rangenumber120Maximum parallax displacement per unit of speed (px)
containerRefObject<HTMLElement | null>Ref of the nested scroll container; when omitted, the window is the scroll container
classNamestringAppended to the class list (which defaults to relative overflow-hidden)

The remaining React.HTMLAttributes<HTMLElement> (such as aria-label, style, id) are forwarded to the root <section>.

ParallaxLayer

PropTypeDefaultDescription
childrenReactNodeThe contents of this layer
speednumber0.5Displacement multiplier; positive values sit toward the foreground (faster, floating up against the scroll), negative values toward the background (slower, sinking with it), 0 means no parallax
axis"x" | "y""y"Axis of displacement
fadebooleanfalseFade in and out at both ends as the section enters and leaves the viewport
decorativebooleanfalseMark the layer as purely decorative (adds aria-hidden, disables pointer events)
classNamestringAppended to the class list

How it works

  • Progress is tracked with useScroll across the full scroll from "the section enters the viewport at the bottom" to "the section leaves the viewport at the top" (offset: ["start end", "end start"]); the midpoint 0.5 is where the section is centered and every layer returns to its natural position.
  • Each layer's displacement is a linear mapping of progress across [+speed·range, -speed·range], so displacement is 0 when the section is centered and grows toward both ends.
  • Parallax layers are usually stacked with absolute inset-0; give ParallaxSection an explicit height and keep the default overflow-hidden so overflowing backgrounds get clipped.
  • The sign of speed sets the depth direction and its magnitude sets the amount of displacement; small negative values work well for background layers, larger positive values for foreground accents.

Accessibility

  • When the user has "reduce motion" enabled at the system level, parallax displacement and fading are disabled automatically, every layer stays at its natural position, and the content remains fully readable.
  • Add decorative to purely decorative layers; it applies aria-hidden and disables pointer events, so assistive technology does not read them out and they cannot be clicked by accident.
  • Parallax only applies transform / opacity, so it does not affect document flow or reading order.

On this page