Layered Parallax
Five SVG mountain ridges, a moon, and the headline all scroll at different velocities — eased through a lerp loop so motion glides instead of stutters.
A zero-dependency scroll experience
Layered parallax. Scroll-drawn SVG. Cinematic motion.
No frameworks. No build step. Just the platform.
The Journey
The Craft
Hover the cards — they track your cursor in 3D. Everything below is hand-rolled with IntersectionObserver, requestAnimationFrame, and SVG geometry. Total JavaScript: one small file.
Five SVG mountain ridges, a moon, and the headline all scroll at different velocities — eased through a lerp loop so motion glides instead of stutters.
The journey path measures its own length with getTotalLength(), then maps your scroll position onto stroke-dashoffset. Waypoints ignite as the ink passes them.
Cards compute pointer position into CSS custom properties, driving a rotateX/rotateY transform and a glare highlight that chases your cursor.
The horizontal gallery below pins itself with position: sticky while vertical scroll is remapped into a sideways pan. No scroll-jacking — your wheel stays in charge.
Only transform and opacity ever animate — properties the compositor handles off the main thread. Observers replace scroll-handler math wherever possible.
Respects prefers-reduced-motion — every parallax layer, twinkle, and tilt quietly steps aside for users who ask for stillness.
You're scrolling down right now — but the page is moving sideways. The section is 300vh tall; its progress through the viewport becomes a translateX.
No libraries pinning the viewport — just position: sticky; top: 0 on a full-height frame inside a tall section. The browser does the hard part.
The pan position chases the real scroll value through exponential smoothing. Flick your wheel — the gallery banks into the motion like it has mass.
Three static files. npx wrangler pages deploy . and it's on Cloudflare's edge in ~300 cities. No bundler, no node_modules, no cold starts.
The Receipts