Skip to content
WANCRAFT

E.172Backgrounds & Effects

Parallax Hills

Layered, seeded landscape silhouettes with atmospheric haze, slow drift and pointer/scroll parallax by depth.

NewReactSVGTailwindadvanced

Overview

Parallax Hills draws an editorial landscape in a single SVG. Ridgelines are generated from seeded, periodic value noise — far ridges tall and craggy (ridged noise), near ones low and rolling — sampled and smoothed into cubic Béziers, with coordinates rounded so the server and client render the exact same scene. Colour comes from CSS custom properties: each layer mixes the land colour toward the haze by depth (atmospheric perspective), valley fog sits between ridges, and a hairline crest picks out each contour. Four palettes — dawn, dusk, mist and night — each have light and dark variants, and the sky gains a moon and stars in the dark theme. Layers drift slowly (the noise tiles seamlessly) and shift with the pointer and with scroll in proportion to their depth; transforms are written from one requestAnimationFrame loop that pauses offscreen and in hidden tabs.

01Installation

Method 01 · Registry

CLI verified

Uses the shadcn CLI in a project initialised with shadcn init. Installs the file to components/ui/parallax-hills.tsx and adds its dependencies.

npx shadcn@latest add https://wancraft.my/r/parallax-hills.json

Method 02 · Copy and paste

  1. 1. No extra dependencies — React and Tailwind CSS only.
  2. 2. Copy the source from the Code tab into components/ui/parallax-hills.tsx.
  3. 3. Import it and adjust props.
Dependencies
None
Peer
react ≥ 18, tailwindcss ≥ 4
Added
13 Oct 2026
Updated
—

02Usage

The default configuration. Change properties above to generate a tailored example in the Usage tab.

example.tsx
import { ParallaxHills } from "@/components/ui/parallax-hills";

export function ParallaxHillsExample() {
  return (
    <div className="relative h-96 w-full overflow-hidden rounded-xl">
      <ParallaxHills />
    </div>
  );
}

03Props

PropTypeDefaultDescription
layersnumber5Number of ridges, far to near (2–7).
palette"dawn" | "dusk" | "mist" | "night""dusk"Colour story; each has light and dark theme variants via CSS custom properties.
seednumber7Seed for the ridge shapes and stars; the same seed always draws the same scene (SSR-safe).
roughnessnumber0.5Ridgeline detail, 0 (rolling) – 1 (craggy).
driftnumber0.3Horizontal drift speed, 0–1; near layers drift faster.
parallaxnumber0.5Pointer and scroll parallax strength, 0–1.
celestialbooleantrueSun on light themes; moon on dark themes and the night palette.
starsbooleantrueStars on dark themes and the night palette.
childrenReactNode—Optional content layered above the scene.
...propsHTMLAttributes<HTMLDivElement>—Forwarded to the root, which is absolute inset-0 — place it inside a positioned parent.

04Features

  • 01Seeded, periodic value noise → Catmull-Rom Béziers; deterministic and rounded for identical SSR output
  • 02Atmospheric perspective with color-mix between land and haze by depth, plus valley fog and hairline crests
  • 03Four palettes with light/dark variants in pure CSS custom properties — no JS needed for theming
  • 04Seamless drift (the noise tiles), and pointer + scroll parallax proportional to each layer's depth
  • 05One rAF loop writing transforms directly; pauses offscreen, in hidden tabs, and when nothing moves
motion · continuousmotion · scroll-linkedinput · pointerinput · scrollinput · viewport

05Accessibility

  • The SVG is aria-hidden; the landscape is decoration and content layered above it stays fully interactive.
  • Pointer parallax only reacts to a mouse; touch users get the drift and scroll parallax, and listeners are passive.
  • With prefers-reduced-motion there is no drift and no parallax — the server-rendered composition stays still.