Major work · July 2025
Risograph.css
A tiny CSS layer that fakes the misregistered, ink-trapped look of real Riso printing — with zero images.
Why it matters
Designers love the Risograph aesthetic but ship it as flat PNGs that bloat pages and break in dark mode. I wanted the texture to be real CSS — themeable, printable, and accessible — instead of a screenshot of a feeling.
What I built
A ~3KB CSS utility set: layered mix-blend-mode multiply channels, an SVG turbulence grain mask, and "misregistration" offsets driven by custom properties. It works on text and boxes, degrades to flat color where blend modes aren't supported, and respects prefers-reduced-motion — the grain never animates.
What I learned
mix-blend-mode is shockingly capable and shockingly easy to make inaccessible. I had to add a contrast-floor guard so the "ink trap" never drops body text below AA. Shipping a design effect as a dependency forces you to document constraints, not just usage.
Risograph printing is gorgeous because it’s a little bit broken. Two ink drums, two passes, and the registration is never quite perfect — so you get these soft overlaps where colors multiply into a third, unplanned ink. Most people reproduce that by exporting a flat raster and calling it a day. That always bothered me: you’ve taken a living, themeable thing and frozen it.
So Risograph.css is the effect rebuilt from CSS primitives. The “ink” is real layered color with
mix-blend-mode: multiply; the grain is an SVG feTurbulence mask, not a tiling JPEG; the
misregistration is a couple of custom-property offsets you can animate or pin. Because it’s CSS,
it inherits your theme, prints sensibly, and weighs almost nothing.
The hard-won feature is the accessibility guard. Blend modes can quietly tank your contrast on a color you never explicitly chose, and that’s exactly the bug that became its own Field Note. The library now ships a contrast floor so the texture can never make your body copy illegible.