Horizontal Depth Fade

Scroll-driven horizontal strip with images on a single line, cinematic blur focus, and brightness falloff.

Installation

File Structure

horizontal-depth-fade.tsx

Usage

import { HorizontalDepthFade } from "@/components/unlumen-ui/horizontal-depth-fade";

const images = [
  { src: "/photos/1.jpg", alt: "Photo 1" },
  { src: "/photos/2.jpg", alt: "Photo 2" },
  { src: "/photos/3.jpg", alt: "Photo 3" },
  { src: "/photos/4.jpg", alt: "Photo 4" },
];

export default function Gallery() {
  return <HorizontalDepthFade images={images} />;
}

With custom strip sizing

<HorizontalDepthFade
  images={images}
  itemWidth={420}
  itemHeight={560}
  gap={20}
  scrollLength={320}
  scrollSensitivity={0.55}
  brightnessBoost={60}
/>

API Reference

images
HorizontalDepthFadeImage[]

Array of image objects to display. Each item has `src` (string) and optional `alt` (string).

travel?
number
100

Horizontal travel amount in percent of available strip overflow. `100` means full traversal.

scrollSensitivity?
number
0.6

Scroll sensitivity multiplier. Lower values require longer scrolling for the same horizontal movement.

blur?
number
10

Maximum blur amount in pixels away from each image focus zone.

dim?
number
20

Minimum brightness percentage away from each focus zone. `0` is black, `100` keeps full brightness.

brightnessBoost?
number
55

Extra brightness at the active focus zone. Useful for stronger cinematic pop.

darknessStrength?
number
1.35

Multiplier for out-of-focus darkening intensity. Values above `1` make the strip darker faster.

minSaturation?
number
0

Minimum saturation percentage away from focus. `0` gives full black-and-white at the edges.

saturationStrength?
number
1.35

Multiplier for out-of-focus desaturation intensity. Values above `1` push images to grayscale faster.

focusSpread?
number
0.16

Normalized spread of the focus window. Lower values make transitions tighter and more dramatic.

scaleEffect?
number
0.09

Scale reduction applied away from focus. Higher values make the depth contrast stronger.

gap?
number | string
"1.5rem"

Gap between strip items. Accepts `number` (px) or CSS string.

itemWidth?
number
360

Width of each image item in the horizontal strip.

itemHeight?
number
460

Height of each image item in the horizontal strip.

scrollLength?
number
360

Scroll section height in viewport units (`vh`). Higher values make horizontal movement more gradual.

scrollContainerRef?
RefObject<HTMLElement | null>

Optional ref to a custom scroll container. Required when the section does not scroll with the viewport.

className?
string

Additional classes applied to the root element.

Notes

  • This component intentionally avoids perspective, rotate, and skew transforms.
  • The visual language relies only on horizontal movement, blur, brightness, and subtle scale.
  • Saturation remains normal in the center and can fall progressively to grayscale near edges.
  • All images stay on a single horizontal line.
  • Animation runtime is GSAP ScrollTrigger only.
  • The section uses a sticky viewport and translates the track as the user scrolls vertically.
  • Use scrollSensitivity + scrollLength together to control how long users need to scroll.

Shader-friendly upgrade ideas

  • RGB split pass: slight per-channel horizontal offsets near the top and bottom edges for a chromatic cinematic look.
  • Luma mask shader: use luminance to fade blur dynamically instead of a linear scroll curve.
  • Grain + vignette pass: a lightweight post-process layer to add texture and focus.
  • Velocity-aware distortion: derive horizontal wave strength from scroll velocity for more reactive motion.

Credits

Built by leo.

Keep in mind

Most components on this site are inspired by or recreated from existing work across the web. I'm not here to take credit; just to learn, experiment, and sometimes push things a bit further. If something looks familiar and I forgot to mention you, reach out and I'll fix that right away.