Skip to content
Template Empire / components

Search components

10 results

Browse components

Parallax Layers

A free parallax section for React and GSAP: layers drift at different depths as you scroll.

  • Automated axe check
  • Reduced-motion tested
  • SSR build verified
  • GSAP
  • 2 runtime packages

Parallax Layers is a free parallax section for React and Next.js, driven by GSAP ScrollTrigger and styled with Tailwind. You pass two to four layers as plain children and set a data-depth attribute from 0 to 1 on each one; as the section scrolls through the viewport, every layer translates vertically at its own rate, scrubbed directly from native scroll, so a depth of 0 stays still and a depth of 1 moves the most.

Movement is transform only around the authored layout, so nothing shifts (CLS 0), and there is no pinning, snapping or scroll-jacking: wheel, keyboard and touch scroll straight through the section natively. With prefers-reduced-motion enabled, or with JavaScript unavailable, no ScrollTrigger is created at all and every layer sits static at its authored position, fully visible.

Scroll storytelling

Depth you can feel, scroll you still own

The glow drifts fastest, the small shapes follow at less than half the rate, and this text does not move at all. Every offset is scrubbed straight from native scrolling, so stopping mid-section freezes the scene, and reduced motion holds every layer still.

Install

Add the @te registry to your components.json once:

{
  "registries": {
    "@te": "https://templateempire.io/r/{name}.json"
  }
}

Then install the component:

npx shadcn@latest add @te/scroll-parallax-layers

Usage

import { ScrollParallaxLayers } from "@/components/scroll-parallax-layers";

export default function Page() {
  return (
    <ScrollParallaxLayers className="overflow-hidden">
      <div
        aria-hidden="true"
        data-depth="1"
        className="pointer-events-none absolute inset-0"
      >
        {/* fast decorative background shapes */}
      </div>
      <div
        aria-hidden="true"
        data-depth="0.4"
        className="pointer-events-none absolute inset-0"
      >
        {/* slower mid-ground accents */}
      </div>
      <div data-depth="0" className="relative py-32">
        <h2>Content that holds still</h2>
        <p>Readable copy lives on the depth-0 layer.</p>
      </div>
    </ScrollParallaxLayers>
  );
}

Props

PropTypeDefaultDescription
childrenReactNoderequiredLayer content. Pass 2 to 4 direct children; each may set a data-depth attribute from 0 to 1 (0 means no movement, 1 means maximum). Missing or invalid values are treated as 0.
classNamestringundefinedAdditional classes merged onto the section root.

Customisation

Parallax Layers declares no tokens of its own: the layers are your own markup, so colours and spacing come from whatever Tailwind classes you put on them, and the movement rate comes from each layer's data-depth attribute. To retheme the section, restyle your layer content directly or override the semantic tokens it consumes from :root or any ancestor:

:root {
  --background: var(--color-neutral-900);
  --foreground: var(--color-neutral-50);
}

Frequently asked questions

Is Parallax Layers free for commercial use?
Yes. Parallax Layers is MIT licensed, so you can use it in personal and commercial projects without attribution.
Does the parallax hurt scrolling, performance or accessibility?
No. Each layer gets one scrub-linked GSAP tween that animates only its transform, mapped with a linear ease across the section's full pass through the viewport, so movement tracks native scrolling exactly and runs at 60fps on the compositor. There is no pinning and no snap, wheel, keyboard and touch all behave natively, and layout is never touched so there is no layout shift. With reduced motion enabled no ScrollTrigger is created at all: every layer renders static at its authored position. Decorative layers in the demo are hidden from assistive technology and never intercept pointer input.
How do I control how far each layer moves?
Set a data-depth attribute between 0 and 1 on each direct child. A layer with depth d translates to -30 percent of its own height multiplied by d over the section's scroll range, so 0 stays still, 0.5 moves at half rate and 1 moves the most. Missing or invalid values are treated as 0, and values outside the range are clamped. Keep readable content on a depth-0 layer and give moving decorative layers extra height so their travel never uncovers a gap.

Related components

Want the full page this belongs to?Template Empire builds complete Next.js templates with this motion system throughout. Browse the paid templates that pair with these free components.Explore Template Empire templates