Faking paper in CSS.
Stains and all.
This chapter renders the Lab as it was — painted entirely in CSS. The surface you’re reading on right now is the old one.
The five layers.
No photographs. Everything below was drawn from CSS gradients, SVG filters, and a lot of careful stacking.
- 1Lunar grey groundFlat
oklch(0.78 0.020 70). Warm enough to read as paper, not steel. - 2Graph paper grid12 px minor + 60 px major lines in aubergine ink. Two stacked linear gradients.
- 3Worn zonesFour radial-gradient masks (composited
intersect) faded the grid in patches. Someone wrote and erased here. - 4Desk lampWarm linear gradient anchored to the top of the body, fading over 90 vh. The room was lit from above.
- 5StainsInline-SVG data URIs. Tea ring. Ink blot. Smudge. Each
mix-blend-mode: multiply. - 6Fibre noise
feTurbulenceat low opacity, multiplied. What every fake-paper surface reaches for eventually.
Where it got us.
The best we could do with code alone. Convincing-ish. Structured. Aligned with the grid — the grid was the grid, because we painted both.
And still, it read as CSS doing paper rather than paper. Zero fibre. Every stain in a fixed position. Every worn zone a radial gradient with perfectly predictable edges. Graph lines running in mathematical straights.
Why we left.
The mockup at /mockup/paper-tile put a 120×120 scan next to this. The scan won immediately.
What survived.
The grid stayed, softened. The desk-lamp metaphor became the dark modefuture. The stains, worn zones, and fibre noise all retired — the photographic paper made each of them redundant.