← Back to STRATA

Build guide · Experiment 06

How STRATA was built.

Concept to production · one session · three polish passes · zero images

The premise

STRATA is a fictional field institute that teaches people to read geological time. The whole site is organized around one honest metaphor: the page is a core sample. You start at the surface at dusk, and everything below the hero is stacked the way rock actually stacks, newest era on top, oldest at the bottom.

Every visual on the page is code. There are no photographs, no stock textures, and no WebGL: just Canvas 2D, SVG, and CSS on top of three Google Fonts.

Art direction

The dusk ridgelines

The hero horizon is six layers of value noise drawn to a canvas. Each layer sums four octaves of interpolated hashes, so ridges stay coherent instead of jittering:

function ridge(seed, x){
  let y = 0, amp = 1, f = 1;
  for (let o = 0; o < 4; o++){
    const xi = Math.floor(x*f), xf = x*f - xi;
    const a = hash(seed+xi), b = hash(seed+xi+1);
    const u = xf*xf*(3-2*xf);          // smoothstep
    y += (a + (b-a)*u) * amp;
    amp *= .5; f *= 2.1;
  }
  return y/1.9;
}

Layers closer to the viewer are darker, drift faster, and get a gentle scroll parallax (yBase + scrollY * (0.16 - shade*0.13)), while the two farthest ridges carry a 1px ember rim light. Forty-two dust motes twinkle upward near the horizon. The loop pauses on visibilitychange and collapses to a single static frame under prefers-reduced-motion.

The column

The centerpiece is an accordion of six era bands built from a data array, each a real <button aria-expanded> controlling a role="region". Heights animate by measuring scrollHeight, transitioning to it, then settling on auto so the layout stays fluid. Only one era opens at a time, like pulling one drawer of a specimen cabinet.

The band colors double as the expanded chapter's background via color-mix(in srgb, var(--era) 55%, var(--rock)), which keeps every open state on-palette for free.

The core rail

A fixed rail on the right renders a miniature core sample: a 5px column whose colored fill is the same era sequence, scaled by scroll progress, next to a live meter readout that counts from 0 to 6,885 m. It is the site's scroll bar, speedometer, and legend at once.

A bug worth remembering

The era rows are styled with all: unset to strip button chrome. That also unsets box-sizing, so width: 100% plus padding quietly overflowed the viewport and clipped the age labels on mobile. The fix is one line, all: unset; box-sizing: border-box;, and it only surfaced because every pass includes real phone-viewport screenshots.

Three passes


Live site: buloy.space/x/strata · All experiments: buloy.space/x