~/css/grain-textures
7 CSS Grain and Noise Textures
7 Pure CSS Published 2026-10-05 Free · no sign-up
Seven texture effects made without image files: film grain from an SVG noise filter, a warm paper texture, a gradient with grain to hide banding, a matte textured button, comic halftone dots, grain over a photo and grain that flickers like projected film.
Filter demos
01. SVG Noise Overlay
Grain Texture
Film grain from an inline SVG feTurbulence filter used as a background image on a pseudo-element, blended over a gradient. The noise is generated by the browser, so it costs no image download and scales to any size.
Copy HTML Copy CSS Open in editor →
View code
HTML CSS
<section class="gr1"><h3>Analog hours</h3><p>Records, coffee and long afternoons.</p></section>.gr1 { position: relative; isolation: isolate; width: 300px; max-width: 100%; padding: 30px 20px; box-sizing: border-box; border-radius: 18px; background: linear-gradient(135deg, #7c2d12, #be123c 60%, #4c1d95); color: #fff7ed; font: 14px Inter, system-ui, sans-serif; overflow: hidden; }
.gr1::after { content: ""; position: absolute; inset: 0; z-index: -1; background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); opacity: .28; mix-blend-mode: overlay; }
.gr1 h3 { margin: 0 0 4px; font-size: 26px; } .gr1 p { margin: 0; color: #fed7aa; }
02. Paper Texture Card
Grain Paper
A note card on a warm paper texture, made from fine noise multiplied over a cream colour. Lower turbulence frequencies give coarser grain; this one is fine enough to feel like paper without distracting from the text.
Copy HTML Copy CSS Open in editor →
View code
HTML CSS
<article class="gr2"><h3>Dear reader,</h3><p>Thank you for ordering from our little studio. Every piece was packed by hand.</p></article>.gr2 { position: relative; isolation: isolate; width: 280px; max-width: 100%; padding: 22px; box-sizing: border-box; border-radius: 6px; background: #faf6ec; color: #3f2d1d; font: 15px/1.6 Georgia, serif; box-shadow: 0 8px 18px -10px rgba(63,45,29,.5); }
.gr2::before { content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit; background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='p'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.65' numOctaves='2'/%3E%3CfeColorMatrix values='0 0 0 0 .4 0 0 0 0 .3 0 0 0 0 .2 0 0 0 .35 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23p)'/%3E%3C/svg%3E"); mix-blend-mode: multiply; }
.gr2 h3 { margin: 0 0 6px; font-style: italic; } .gr2 p { margin: 0; }
03. Grainy Gradient Background
Grain Gradient
Smooth gradients can show visible banding on some screens. A light layer of grain breaks up the bands and gives the colour a printed, tactile quality, a popular look for modern landing pages.
Copy HTML Copy CSS Open in editor →
View code
HTML CSS
<section class="gr3"><p>No banding, just grain.</p></section>.gr3 { position: relative; display: grid; place-items: center; width: 300px; max-width: 100%; height: 200px; border-radius: 18px; background: radial-gradient(circle at 20% 20%, #f472b6, transparent 50%), radial-gradient(circle at 80% 80%, #38bdf8, transparent 55%), #312e81; font: 700 16px Inter, system-ui, sans-serif; color: #fff; overflow: hidden; }
.gr3::after { content: ""; position: absolute; inset: 0; background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.2' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23g)'/%3E%3C/svg%3E"); opacity: .22; mix-blend-mode: soft-light; pointer-events: none; }
.gr3 p { position: relative; margin: 0; padding: 6px 12px; border-radius: 8px; background: rgba(15,23,42,.45); }
04. Grain-Textured Button
Grain Button
A button with a subtle grain on its fill, which makes a flat colour feel like riso print or matte plastic. The grain is a background layer over the colour, so the text stays crisp on top.
Copy HTML Copy CSS Open in editor →
View code
HTML CSS
<button class="gr4">Order prints</button>.gr4 { padding: 14px 26px; border: 0; border-radius: 12px; background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='b'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.1' numOctaves='2'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 .2 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23b)'/%3E%3C/svg%3E"), #0f766e; color: #fff; font: 800 15px Inter, system-ui, sans-serif; cursor: pointer; }
.gr4:hover { background-color: #115e59; }
.gr4:focus-visible { outline: 3px solid #5eead4; outline-offset: 3px; }
05. Halftone Dot Texture
Grain Halftone
A comic-book halftone made from a radial-gradient dot pattern, masked so the dots fade out across the panel. Unlike noise, halftone is regular, which gives a graphic, printed feel rather than a photographic one.
Copy HTML Copy CSS Open in editor →
View code
HTML CSS
<section class="gr5"><h3>POW!</h3></section>.gr5 { position: relative; display: grid; place-items: center; width: 280px; max-width: 100%; height: 190px; box-sizing: border-box; border: 3px solid #111; background: #fde047; overflow: hidden; }
.gr5::before { content: ""; position: absolute; inset: 0; background: radial-gradient(circle, #f97316 2.5px, transparent 3px) 0 0 / 10px 10px; -webkit-mask: linear-gradient(120deg, #000 10%, transparent 75%); mask: linear-gradient(120deg, #000 10%, transparent 75%); }
.gr5 h3 { position: relative; margin: 0; color: #111; font: 900 56px Impact, "Arial Black", sans-serif; transform: rotate(-6deg); text-shadow: 4px 4px 0 #fff; }
06. Grain over an Image Card
Grain Image
A card where grain sits over the picture but under the caption, giving the image a film-photo quality while keeping the text sharp. The stacking is three layers: image, grain pseudo-element and caption.
Copy HTML Copy CSS Open in editor →
View code
HTML CSS
<figure class="gr6"><div class="im" role="img" aria-label="Sunset over a harbour"></div><figcaption>Harbour, 35 mm</figcaption></figure>.gr6 { position: relative; width: 260px; max-width: 100%; margin: 0; border-radius: 14px; overflow: hidden; font: 600 13px Inter, system-ui, sans-serif; }
.gr6 .im { aspect-ratio: 4 / 3; background: linear-gradient(#fdba74, #f472b6 45%, #1e3a8a 46%, #0f172a); }
.gr6::after { content: ""; position: absolute; inset: 0; background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='f'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23f)'/%3E%3C/svg%3E"); opacity: .3; mix-blend-mode: overlay; pointer-events: none; }
.gr6 figcaption { position: absolute; left: 10px; bottom: 10px; z-index: 1; padding: 4px 8px; border-radius: 6px; background: rgba(0,0,0,.6); color: #fff; }
07. Flickering Film Grain
Grain Animation
Grain that jumps position in quick steps, like the flicker of projected film. The noise layer is larger than the panel and moves between offsets with steps(), and it stays still for anyone who prefers reduced motion.
Copy HTML Copy CSS Open in editor →
View code
HTML CSS
<section class="gr7"><h3>The Long Night</h3><p>A short film · 2026</p></section>.gr7 { position: relative; isolation: isolate; width: 300px; max-width: 100%; padding: 36px 20px; box-sizing: border-box; border-radius: 16px; background: #1c1917; color: #f5f5f4; font: 14px Georgia, serif; text-align: center; overflow: hidden; }
.gr7::after { content: ""; position: absolute; inset: -50%; z-index: -1; background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='m'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23m)'/%3E%3C/svg%3E"); opacity: .18; animation: gr7 .6s steps(3) infinite; }
.gr7 h3 { margin: 0 0 6px; font-size: 26px; letter-spacing: .08em; } .gr7 p { margin: 0; color: #d6d3d1; }
@keyframes gr7 { 0% { transform: translate(0, 0); } 33% { transform: translate(-12%, 8%); } 66% { transform: translate(9%, -10%); } }
@media (prefers-reduced-motion: reduce) { .gr7::after { animation: none; } }
About these CSS Grain and Noise Textures
Noise from SVG
An inline SVG with feTurbulence generates noise in the browser. Used as a data URL background, it needs no download and tiles at any size.
Blend it in
Lay the noise over colour with mix-blend-mode (overlay, soft-light or multiply) and a low opacity. A little grain goes a long way.
Grain fixes banding
Large smooth gradients can show visible steps on some screens. A faint grain layer breaks them up and makes the colour feel richer.
Keep text off the noise
Put grain behind or under text layers, not over them, so letters stay crisp and readable.
Frequently asked questions
Does SVG noise hurt performance? Static noise is cheap. Animated noise over large areas costs more, so keep it small or pause it.
Can I change the grain size? Lower baseFrequency gives coarser grain; higher gives finer.
Does the flicker respect reduced motion? Yes, it stops under prefers-reduced-motion.