Paper grain
Paper · Pure CSS
The page looks printed on uncoated paper: a fine, even grain of fibres over a slightly warmer centre, with a faint darker vignette at the edges like a sheet under a desk lamp. Static and quiet; text stays crisp on top.
✓ (1×) · claude-haiku-5-5 → claude-opus-5-5# Build the "Paper grain" background effect (`paper-grain`)
Family: Paper · pure CSS. Fine fibre grain and a soft vignette, like an uncoated printed sheet.
## Look
The page looks printed on uncoated paper: a fine, even grain of fibres over a slightly warmer centre, with a faint darker vignette at the edges like a sheet under a desk lamp. Static and quiet; text stays crisp on top.
## Parameters (current values)
- Grain `--fx-grain`: 0.22 (range 0–0.6) — strength of the fibres
- Vignette `--fx-vignette`: 0.35 (range 0–1)
- Paper `--fx-color-bg`: the `bg` colour token, `var(--c-bg)`
- Centre tint `--fx-color-tint`: the `surface` colour token, `var(--c-surface)`
- Grain and vignette `--fx-color-ink`: the `text` colour token, `var(--c-text)`
## Recipe
- The element: `background: radial-gradient(120% 90% at 50% 40%, color-mix(in srgb, var(--fx-color-tint) 60%, transparent), transparent 70%), var(--fx-color-bg)`.
- Grain on `::before` (`content: ''; position: absolute; inset: 0`): `background-color: var(--fx-color-ink)` shaped by a noise mask, so the grain takes the token colour — `mask-image` and `-webkit-mask-image` set to an inline `url("data:image/svg+xml,…")` SVG of 200×200 with `<filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='3' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -2.2 1.4'/></filter><rect width='100%' height='100%' filter='url(%23n)'/>` (the matrix turns noise into alpha), `mask-size: 200px 200px`, and `opacity: var(--fx-grain)`.
- Vignette on `::after` (same box): `background: radial-gradient(ellipse at 50% 45%, transparent 55%, color-mix(in srgb, var(--fx-color-ink) calc(var(--fx-vignette) * 30%), transparent) 100%)`.
- Encode the SVG for CSS: single quotes inside, `#` as `%23`, `<` and `>` may stay or be encoded as `%3C` and `%3E`.
## CSS fallback
It is pure CSS: the result above is the whole effect.
## Runtime rules
- Mount it in one element that fills a fixed, `pointer-events: none`, `aria-hidden` layer behind the page content; every parameter above is a CSS custom property on that element.
- Colours come only from the colour-token variables above (mix them with `color-mix()` or alpha), never hard-coded hex, so the effect follows any palette and light or dark mode.
- CSS only: gradients, `mask`, pseudo-elements and inline `data:image/svg+xml` (no `<script>` or `<image>` inside it). No images, remote URLs, `@import` or JavaScript. Keep it under ~8 KB.
- It is static: no animation.
## Avoid
- Coarse grain (baseFrequency below 0.6) or visible tile seams (keep stitchTiles)
- Any animation, including flickering grain
- Grain stronger than 0.6 — text turns muddy
- Raster images, `<image>` or scripts inside the SVGCopied!