Noise Overlay
Film grain that shivers on any surface: an SVG noise layer at 15% shifts by one pixel every 20 ms, without a single line of JavaScript.
Updated
This effect is part of Effect.Labs — 840 vanilla effects, some free, some premium. Distortion has 31 effects, including 5 free. Explore the category →
3 usage examples



How it works
The surface .fgr-box (250×150 px by default, indigo to violet gradient) holds two children: the .fgr-grain layer and your own .fgr-content. The layer is an SVG image embedded as data:: an feTurbulence filter of type fractalNoise (frequency 0.8, 4 octaves) that yields a fine coloured noise. No external image is loaded.
The grain comes alive through the fgr-move animation: over 0.2 s and 10 steps (steps(10)), the layer slides 10 px up and left, then the loop starts again. The pattern therefore jumps one pixel every 20 ms, like the grain of running film stock. The layer overhangs by 10 px on the right and bottom so this slide never uncovers a bare strip at the edge.
The .fgr-content sits above the grain (z-index: 1) and stays perfectly crisp: only the background is textured. Everything is tuned through CSS variables set on .fx-0256-root: size, background, corner radius, grain strength and pace. With --fgr-w: 100% and --fgr-h: 100% the surface fills its container, so a whole page header can be textured.
Measured in Chromium 151, Firefox 153 and WebKit 26.5: two copies on the same page each run on their own, nothing is added to window, no errors. The layer does not flash (constant average luminance, frame-by-frame measurement at 20 ms).
Accessibility
- Reduced motion: under
prefers-reduced-motion: reduce, thefgr-moveanimation is switched off. The grain stays visible, still: the texture is kept, only the shimmer goes. - Legibility: the grain lies under the content, never over it. At 15% it does not hinder reading; above 40% on a light background, check the contrast of your text.
- Screen readers: the layer has
aria-hidden="true". Only the text inside.fgr-contentis read. If the surface stands for an image (record sleeve, photo), give itrole="img"and anaria-label. - Keyboard and touch: nothing to activate, the effect is purely decorative. The layer has
pointer-events: none: links and buttons placed in.fgr-contentstay clickable.
Browser compatibility
CSS only: CSS variables, @keyframes with steps() and an feTurbulence SVG image as data:. Minimum versions from MDN data (CSS variables: Chrome 49, Firefox 31, Safari 9.1). Measured in Chromium 151, Firefox 153 and WebKit 26.5: same rendering and animation.
Without CSS variables the surface loses its size and background (browsers older than 2016). If the SVG image is not rendered, the surface stays plain with its content: nothing breaks.
The code
HTML structure to paste into your page (the CSS + JS come with your purchase):
<div class="fx-0256-root">
<div class="fgr-box">
<div class="fgr-grain" aria-hidden="true"></div>
<span class="fgr-content">…</span>
</div>
</div>
One-time payment, no subscription — the code is yours forever
Customize
Options passed to the API or data-* attributes:
| Option / property | Default | Effect |
|---|---|---|
--fgr-w / --fgr-h |
250px / 150px |
Size of the textured surface. 100% fills the container (the root then needs a height, see --fgr-root-h). The width never exceeds the root's. |
--fgr-bg |
linear-gradient(135deg, #6366f1, #8b5cf6) |
Background under the grain: colour, gradient or photo (url(photo.jpg) center / cover). |
--fgr-opacity |
.15 |
Grain strength. Around .3–.45 it shows clearly; at .05 it becomes a mere patina. |
--fgr-speed |
.2s |
Duration of one 10-step loop. .4s gives a calmer grain; 1s a slow shimmer. |
--fgr-radius |
12px |
Corner radius of the surface; 0 for a section background. |
--fgr-root-bg / --fgr-root-h |
#0a0a0f / 300px |
Background and minimum height of the root that centres the surface. transparent to lay the effect on your page, 0 so the root hugs the surface. |
Content (HTML — .fgr-content) |
Text “GRAIN” | Replace it with any content: heading, menu, button. It sits above the grain and stays crisp. |
FAQ
background-size: 300px to .fgr-grain (the pattern then repeats as tiles).fractalNoise filter produces noise on all four channels (red, green, blue, transparency). For a neutral grain, add filter: grayscale(1) to .fgr-grain.transform animation per surface, which the browser hands to the graphics card. The noise image is computed once and then only moved. No JavaScript runs.