A mountain that moves when you scroll

Most parallax heroes move the text and leave the world sitting still. This one does the opposite: the type holds dead still while the mountains pull away from you. That's the whole trick, and it's one copy-paste away.

Nothing to generate, nothing to download. Every plate and the courtyard clip are hosted on this site, and the prompt already points at them. Paste it into Claude and you get the finished page. Want the source? Download the project (8.5 MB) — or scroll the live demo ↗ first.

The prompt

Paste this into Claude and let it run. Nothing to attach — the plates and the video load from their URLs. Open the file it gives you straight off your desktop.

Prompt — click to copy
Build me a single self-contained HTML file: one scroll-driven parallax hero for a fictional slow-travel brand called Rare Air. One file, inline CSS and JS, no CDN links, no build step, no framework.

THE PLATES — load these straight from the URLs, do not download or inline them:

  sky              https://thinkingods.com/downloads/ladakh/01-sky.webp ridge            https://thinkingods.com/downloads/ladakh/02-ridge.webp hills            https://thinkingods.com/downloads/ladakh/03-hills.webp monastery        https://thinkingods.com/downloads/ladakh/04-monastery.webp gate left        https://thinkingods.com/downloads/ladakh/05-gate-left.webp gate right       https://thinkingods.com/downloads/ladakh/06-gate-right.webp courtyard still  https://thinkingods.com/downloads/ladakh/08-courtyard-still.webp courtyard video  https://thinkingods.com/downloads/ladakh-courtyard.mp4

Stack them back to front. Sky at z0, full-bleed, object-fit cover, scale 1.05. Ridge at z1, bottom 34%, width 110%, opacity .58, mix-blend-mode screen, masked so its top fades into the sky. Hills at z2, bottom 0, width 161%, transform-origin 50% 100%. Monastery at z3, left 50%, bottom 0, width min(46vw,760px), transform-origin 50% 100%, flush to the bottom edge — no margin, no gap. Courtyard at z5, full-bleed, object-fit cover. Gate left and right at z6, hinging at 26% 50% and 74% 50%.

The courtyard is a <video> pointed at that MP4: muted, playsinline, preload metadata, with the still image underneath as a fallback layer in the same box. Play it from frame 0 each time the beat is entered rather than looping — the monks walk toward camera, so a loop snaps them back mid-stride. Reset currentTime to 0 on entry, pause on exit.

THE MECHANISM: a tall track with a position:sticky stage inside it. Map scroll distance into CSS custom properties through a smoothstep, throttle on requestAnimationFrame, and ease the mapped value toward its target with a lerp factor of 0.14. Every layer reads those variables — never write per-layer styles from JS. Add a light pointer parallax on top, each layer offsetting by a different amount.

THE BEATS, over a 4100px track:

Beat 0, the world settles, 0 to 720. The hills dolly out: one uniform scale, 1.00 to 0.70, anchored to the bottom edge. NOT a scaleY squash. Because the origin is the bottom, receding reads as the ridgeline sliding down the frame. The ridge pulls back only slightly, 1.00 to 0.92, because it is far away — that difference in rate is the parallax. The ridge also drops 54px and lifts from .58 to .78 opacity, opening up the snowline. The monastery grows 1.00 to 1.15. The title and lede hold on screen through all of it. Nothing typographic moves until the world has finished settling.

Beat 1, the type leaves, 780 to 1340. Title rises 230px and fades, letter-spacing opening .16em to .21em. Lede drops 80px and fades. Only now does the camera push begin.

Beat 2, the gate rises, 1220 to 2020. Gate halves fade up from .52 scale and 16vh below centre. Behind them the camera pushes: hills and ridge scale up and blur softly, the monastery grows to 1.6x and fades out.

Beat 3, the gate parts, 2350 to 3200. The halves slide apart to plus and minus 56vw while still scaling up, as if you are walking through.

Beat 4, the courtyard, 2180 to 2850. Full-bleed courtyard settles from 1.16 scale to 1.0 as it fades in. Then 3340 to 3960 it defocuses: 11px blur, brightness to .62, radial vignette closing in.

Two short caption panels fade in and out over beats 2 and 4.

TYPE AND COLOUR: Cormorant Garamond for display, the word Ladakh set huge, thin, wide letter-spacing, centred. Archivo for UI and body. Paper #EDE4D4, ink #241A12, ochre #B08B5C, umber #6B4A32, cobalt #2E5C8A. The lede reads: Nine days at four thousand metres. Thin air, long light, and a road that ends where the mountains start. Position it low with a soft radial gradient behind it so it stays readable over the monastery.

Bind keys 1 to 6 to smooth-scroll to each beat. Honour prefers-reduced-motion by snapping to scroll position with no easing.
The dolly-out is what sells it. Pulling the hills back to 0.70 from a bottom origin reads as a camera stepping away — not as an image shrinking. Everyone animates the text; almost nobody moves the world and holds the type still.

Landing frame, and beat 2 — the gate rising with the monastery still visible through the opening.

Make it yours

Swap three things in the prompt and it stops being Ladakh:

Prompt — click to copy
- The palette. --paper, --ink, --ochre, --umber, --cobalt are all on :root
- The hero word and the lede. One place name set huge, one sentence underneath. Both are plain text in the markup
- The place itself. Swap the seven URLs for your own plates — far ridge, near hills, one hero object, a gate, an interior. Keep the layer order

Re-run the prompt with your changes rather than editing the output by hand — the beat numbers stay consistent that way. The bundle above carries the Midjourney prompts that made these plates and the Google Flow prompt behind the clip, if you want to generate your own set.

Built something with this?

Tag @thinkingods — I genuinely want to see it. Need a site built properly? Start a conversation.

All prompts
PreviousTurn one prompt into a premium Hero section