A touch of noise is the easiest way to stop a flat-colour background from looking
lifeless. This generator builds that grain as an SVG feTurbulence filter, so the
texture is resolution-independent, weighs almost nothing, and drops straight into
your CSS as a background-image.
How it works
SVG ships with a procedural noise filter. The feTurbulence primitive produces
Perlin or fractal noise, and a feColorMatrix desaturates it to a neutral grain:
<filter id="noise">
<feTurbulence type="fractalNoise" baseFrequency="0.8" numOctaves="3" stitchTiles="stitch"/>
<feColorMatrix type="saturate" values="0"/>
</filter>
<rect width="100%" height="100%" filter="url(#noise)" opacity="0.15"/>
baseFrequency sets how dense the grain is, numOctaves adds detail layers, and
the rectangle’s opacity keeps the effect subtle. The whole SVG is then
URL-encoded into a data:image/svg+xml URI so it can sit inside url().
Tips and notes
Keep opacity low — somewhere around 0.05 to 0.2 reads as texture rather than
static. Use stitchTiles="stitch" (already included) so the noise tiles seamlessly
if the element repeats. Pair the noise layer with a background-color underneath
it, since the grain itself is transparent grey and needs a colour to sit on. Avoid
animating baseFrequency, as recomputing turbulence each frame is one of the more
expensive filter operations in a browser.