Build guide · Experiment 06
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.
#0e0c0a, bone #e9e2d4, and a single ember accent
#c96f3b. Each era band then gets its own earthy color (umber, deep green, slate blue, rust, basalt)
so the column reads like a real stratigraphic chart.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 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.
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.
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.
reduced used before declaration) killed the whole script; the screenshot
harness caught it because it fails on any console error.Live site: buloy.space/x/strata · All experiments: buloy.space/x