Horizontal World · 18

← Back to the catalogue

HorizontalWorld

Eight bays of an editorial journey, and your scroll wheel is driving it sideways. Nothing is hijacked: the document really is eight viewports tall, and the browser is really doing the scrolling — we only read the position.

Scroll or drag to travel · 1–4 change the look · H folds the dock

Scroll to travel
Bay 01 · The cut

One scalar, three consequences

The scroll position is normalised into a single number X, in bays. That number sets the track's transform, each bay's arrival and departure opacity, and a perspective offset on the plinths. There is no second state and no second timer, so the plate, the words and the rail can never disagree about where the reader is.

The consequence worth naming is the one that costs nothing: because the transform is derived from the real scroll position, the browser's own scrollbar works. Flick it, drag it, use a trackpad's momentum, jump with the spacebar — all of it lands in the right place, with no wheel handler anywhere in the file.

Track width
—
Document height
—
Bay 02 · The garment

The subject is drawn, not photographed

Each plate is a Canvas2D composition: a horizon, a vertical gradient built from the look's own six colours, a silhouette whose profile is a sum of four sines, a plinth shadow, and a floor reflection that is a flipped, faded, blurred copy of the same shape. No image is fetched, because there is no image.

It is not a stand-in for a photograph and it is not pretending to be one. It is the reason a client can ship a nine-bay collection page the same afternoon and re-skin it for the next collection by editing six numbers.

Bay 03 · The depth

Depth is a perspective offset, not a shadow

Each bay's plate is drawn twice into the gallery: once at its own bay's parallax factor and once at the factor of the bay you are heading for, cross-faded on X. The result is that the plate of the next bay is already there, sliding in from the side at a different rate, which is the only cue that actually reads as lateral travel rather than as a slideshow.

The knob in the dock changes the parallax spread live. Drag it and the two rates separate — that is the whole depth model, and it is one number wide.

Parallax spread
—
Plates drawn
—
Bay 04 · The grade

Four looks, six numbers each

A look on this page is six numbers: two sky stops, the subject's three-stop ramp, and the floor. The chips in the dock are not filter values — switching look re-seeds every plate, the grain, the rail gradient and the accent the copy is set in, so the change is in the frame you are looking at, not in a number beside it.

Try it: press Nocturne and the room goes cold and blue while the words stay legible, because the ink ramp was chosen against the darkest subject stop rather than against a swatch.

Bay 05 · The arrival

A bay earns its place or loses it

The opacity ladder is a raised cosine over a bay's own two thirds: a bay is fully opaque while it is yours and fades across a third of a bay either side. Narrow that window and the journey reads as a queue of cards; open it and it reads as a corridor. The dock's Arrival knob is that window, and it is the control worth fiddling with.

Nothing is ever at zero opacity while it is on screen, because a bay you can read the words of and cannot see the plate of is a bay that has failed at being a bay.

Bay 06 · The touch

Dragging works because it is not special

On a touch device the drag handler does not move the track directly. It nudges the document's own scroll position with scrollTo, which means the drag and the wheel run through exactly one code path and exactly one state variable. A drag that moved the transform would immediately desynchronise from the scrollbar, and the first flick after the drag would snap.

That is why there is no touchmove with a preventDefault on it anywhere in this file, and why the page can still be scrolled with a keyboard.

Bay 07 · The reading

It is still a page, in every direction

The bays are in the document flow. A screen reader walks them in order, finds eight <h2>s and the prose under each, and never learns that anything moved. With JavaScript off the page is a vertical gallery of the same eight bays, because the default height is one viewport per bay and the transform is an enhancement.

Reduced motion gets that same stack, deliberately. A reader who has asked for less movement gets the composition without the travel, which is the honest reading of what they asked for.

Horizontal World — the catalogue block

Technique
Scroll-routed horizontal gallery: a translate3d track driven by the document's real scroll position, eight Canvas2D plates, and a raised-cosine arrival ladder
What it does
Turns vertical scroll into lateral travel through an eight-bay editorial sequence — a collection, a product journey, a case-study corridor. The document is genuinely eight viewports tall, so the browser's own scrollbar, keyboard paging and momentum all work without a wheel handler. Bays arrive on a raised cosine and leave on the same curve, and each bay's plate is drawn twice into the gallery at two parallax rates for real depth.
Live demo
Four look chips and five knobs in the dock, all of which change the rendered plates in the same viewport. Hold stops the render loop on the current frame. The eight jump buttons travel to a bay by scrolling the document — they are shortcuts, and every bay is also reachable by scrolling or by the rail. —
What it's good for
Fashion and product journeys · lookbooks · exhibition microsites · any narrative that wants to feel like a runway rather than a page
Combines with
Real photography swapped in per bay · audio that scrubs with X · a cart that reads the current bay · the cinematic-scroll rig as the opening shot
Complexity
Advanced — one scalar of state, eight drawn plates, a two-rate parallax gallery, and a no-script stack as the base state rather than a fallback
Performance
What is rendered: eight 2D canvases at up to 1.1 M pixels each, redrawn only when the look changes, a CSS transform per frame, and eight opacity writes. What degrades: the plates are not repainted per frame — they are static compositions and moving them is a compositor's job, not a painter's. On a browser with no 2D context the page keeps its transform, its words and its controls and simply loses the plates rather than going black. —
— bays travelled, out of eight. Read out of the same scalar that positions the track and fills the rail, so it cannot disagree with either.
HORIZONTAL WORLD · chapter 18 · single file · zero network requests after the document
render: Canvas2D plates · one scalar of state · no wheel handler, no preventDefault
no script and reduced motion: the same eight bays, stacked vertically, same palette