A fashion week show is the best product page fashion has: every look walks toward you, stops, and you get a good long look. Then it is on a white background in a grid for the rest of its life. I wanted the store to be the show. Take your seat at avivashishta.com/lab/runway.
You sit at the end of the catwalk. Scroll, and the models walk out of the lit door at the far end, one after another, getting bigger as they come. The one at the front stops, the cameras in the crowd go off, and her look is for sale on the left, piece by piece. Scroll on and she turns off past you while the next one arrives.
The short version: Codex makes one photo of an empty catwalk and one photo of the model walking toward the camera. Every other look is that photo with only the outfit changed. A script cuts each one out with macOS Vision. The page puts each look somewhere between the door and the front, sizes her by perspective and stands her feet on the floor below the vanishing point. The scroll is walking speed, and CSS scroll snap makes every stop a look at the front.
Step 1: the room (Codex)
The catwalk has to be empty and photographed straight down its length, so it has one vanishing point that every model can walk out of.
An empty fashion show runway photographed from the very end of the catwalk, looking straight down its length, eye level, one-point perspective with the vanishing point in the centre of the frame. A long glossy white runway floor with soft reflections, a tall plain warm white wall at the far end with a soft lit entrance opening, rows of seated audience in soft shadow on both sides of the runway (people in dark clothes, faces not detailed), a few phones raised. No model on the runway, nobody standing on it. Soft overhead spotlights, editorial fashion week photography, calm and premium. No text, no logos, no screens with text. Landscape 3:2, 1536x1024.
Step 2: one model, eight looks
The first look is a new photo: her, mid-stride, walking at the camera, on white. Every other look is an edit of it that changes only the clothes. That is what makes eight models feel like one show: the same woman, the same walk, the same light.
The attached image is a full-length fashion photo of a model walking toward the camera. Change ONLY her outfit: she now wears a sharp cobalt blue tailored suit, a single-breasted blazer with nothing underneath and wide matching trousers, with black pointed heels. Keep EVERYTHING else identical: the same woman, face, hair and expression, the same pose and stride, the same arms, the same framing, scale and position in the frame, the same light and the same pure white background. Whole body visible head to shoes. Photoreal. No text, no logos. Portrait 2:3, 1024x1536.
The prep script cuts each look out with macOS Vision and trims it to her, so the top of the image is the top of her head and the bottom is her shoes. That is all the page needs to stand her on the floor.
bun scripts/prepare-runway.mjs ./raw
Step 3: perspective with two numbers
The photo covers the screen, so first the page works out where its vanishing point (the foot of the door) lands on this screen. Then each look has a place on the catwalk, z, from 0 at the door to 1 at the front. How big she is comes from how far away she is, and the distance shrinks evenly as she walks, so she grows slowly at first and quickly at the end, as people do when they walk at you:
const z = 1 + u / WALK; // 0 at the door, 1 at the front
const s = 1 / (7 - 6 * z); // her size: 1/7 at the door, 1 at the front
const h = front * s;
const y = hy + FEET * h - h; // feet below the horizon, by her own height
The last line is the one that makes it look right. The camera is at about eye level, so the horizon cuts through her eyes at any distance, and her feet are always about nine tenths of her height below it. Get that wrong and the models float or sink.
A small bob tied to the distance walked makes her step, and a flipped copy under her, faded with a mask, is her reflection in the glossy floor.
Step 4: the scroll is walking speed
Every look is one screen of scroll, and the page has CSS scroll snap on, so wherever you stop, a look is standing at the front:
html:has(.page) { scroll-snap-type: y mandatory; }
.snap { height: 100svh; scroll-snap-align: start; }
Look i is at the front when you have scrolled i screens. Before that it is walking in from the door; it leaves the door almost two screens early, so there is always someone on the catwalk behind her. After it, she turns off to one side, gets bigger, blurs and fades as she passes the camera. The page follows the scroll with a little lag, so a flick turns into a few quick steps instead of a jump.
The small things
- The cameras go off when a look stops: flashes pop in the crowd on both sides and the room washes white for a moment. Turn the sound on for a shutter burst.
- The first look walks in on load, from the door to the front, before you have touched anything.
- Shop the piece or the look. The panel lists every piece with its price and a plus, and "Shop the look" adds the lot.
- The line-up on the right shows all eight looks; click one and the show walks to it.
Build your own
Build a scroll-driven runway store (React, no libraries). Assets: stage.webp, a photo straight down an empty catwalk with its vanishing point at known fractions of the image, and one cut-out WebP per look, trimmed so the top is the head and the bottom is the shoes. Cover the screen with the photo in a fixed layer and work out where its vanishing point lands. Make the page one 100svh section per look with scroll-snap-type y mandatory.
Each frame, take t = scroll / screen height, smoothed. For look i, u = t - i. While -1.9 < u <= 0 she walks in: z = 1 + u / 1.9, scale s = 1 / (7 - 6z), height = s times her height at the front, x centred on the vanishing point, feet 0.92 of her height below the horizon. For 0 < u < 0.55 she turns off to one side, growing, blurring and fading. Add a small bob tied to u and a flipped, masked copy below her for the floor reflection. When a look stops at the front, flash cameras in the crowd. Show the look's pieces and prices in a panel with Add buttons, and a line-up of all looks that scrolls to each.