VeloxUI
scroll·free

Parallax

Scrub-linked vertical parallax for images and blocks.

speed 0.15
speed 0.4
speed 0.7

Installation

terminal
pnpm add gsap @gsap/react

Then copy the component below into src/components/motion/parallax.tsx. It expects @/lib/gsap (plugin registration) and @/lib/utils (cn).

Source

src/components/motion/parallax.tsx
"use client";

import { useRef, type ReactNode } from "react";
import { gsap, useGSAP } from "@/lib/gsap";
import { cn } from "@/lib/utils";

export interface ParallaxProps {
  children: ReactNode;
  className?: string;
  /** Positive moves slower than scroll (background feel); negative moves faster. Range -1..1. */
  speed?: number;
}

export function Parallax({ children, className, speed = 0.3 }: ParallaxProps) {
  const ref = useRef<HTMLDivElement>(null);

  useGSAP(
    () => {
      const el = ref.current;
      if (!el) return;
      const travel = window.innerHeight * speed;
      gsap.fromTo(
        el,
        { y: -travel / 2 },
        {
          y: travel / 2,
          ease: "none",
          scrollTrigger: { trigger: el, start: "top bottom", end: "bottom top", scrub: true },
        }
      );
    },
    { scope: ref, dependencies: [speed] }
  );

  return (
    <div ref={ref} className={cn("will-change-transform", className)}>
      {children}
    </div>
  );
}