Create a grainy noise background using pure SVG filters and Tailwind CSS. Learn how feTurbulence, feFlood, and feComposite work - no image files or canvas.
Written by: Chia1104 CC BY-NC-SA 4.0
Recently on X, I saw someone share a way to achieve a noise background effect purely through HTML's SVG filters. In the past, the simplest way to do this kind of background effect was to use an image as the base, or to write your own GLSL and implement the relevant algorithm on a canvas. So thanks to @guerriero_se for sharing the SVG approach.

<figure
class="pointer-events-none absolute inset-0 z-10 opacity-10 mix-blend-screen filter-[url('#noise-bg-fx')_grayscale(100%)]"
aria-hidden="true">
<svg>
<filter id="noise-bg-fx">
<feTurbulence baseFrequency="0.8" />
</filter>
</svg>
</figure>| Class | What It Does |
|---|---|
mix-blend-screen | The screen blend mode, which "lightens" against the layer below: black has no effect, while the bright noise specks brighten the underlying layer. The result feels more natural than simply pasting the noise on top. |
filter-[url('#noise-bg-fx')_grayscale(100%)] | Tailwind's arbitrary value syntax. It applies two filters: first the SVG filter #noise-bg-fx, then grayscale(100%) to desaturate it into gray-white noise (the _ is how you write a space in Tailwind). |
feTurbulence:Uses the Perlin noise algorithm to programmatically generate a "turbulence / fractal noise" texture, with no image file required.baseFrequency="0.8":The frequency of the noise. The larger the value, the finer and denser the grain — more like fine sand; the smaller the value, the more it becomes large, cloud-like blobs. 0.8 is on the high side, so it produces a fine, grainy texture.By default, feTurbulence generates noise separately across the R/G/B/A channels, so it is colored to begin with - which is why we used grayscale(100%) earlier to compress it into grayscale.
Here we can use the SVG feFlood and feComposite primitives to apply color: first treat the noise as a transparency (alpha) mask, then pour in the color you want.
The grayscale(100%) on the figure can now be removed as well.
<figure
class="pointer-events-none absolute inset-0 z-10 mix-blend-screen filter-[url('#noise-bg-fx')]"
aria-hidden="true">
<svg>
<filter id="noise-bg-fx">
<feTurbulence type="fractalNoise" baseFrequency="0.8" numOctaves="2" result="noise" />
<!-- Take one channel of the noise to use as the alpha -->
<feColorMatrix in="noise" type="matrix"
values="0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
1 0 0 0 0" result="mask" />
<!-- Pour in the color you want, e.g. blue -->
<feFlood flood-color="#3b82f6" result="color" />
<feComposite in="color" in2="mask" operator="in" />
</filter>
</svg>
</figure>