20 Tailwind CSS Grain Texture

19 Pure Tailwind1 Tailwind + JSPublished

20 Tailwind CSS grain textures for photo heroes, tactile product cards, textured buttons and inputs, print-style halftone and risograph effects, woven fabric surfaces, and dark-mode-safe noise — with SVG <feTurbulence> noise, data-URI textures, anti-banding gradients, dithering, letterpress, and section dividers. Scoped under .gtw-NN for no-collision pasting, prefers-reduced-motion guarded, framework-agnostic.

Related20 Tailwind Liquid Glass Effects20 CSS Neon Effects18 CSS Gradient UI20 CSS Liquid Glass Effects

Premium upgradePartner: Untitled UI

Affiliate link

Building a whole Tailwind app, not just this component?

You just browsed 20 Tailwind grain texture. Untitled UI Pro unlocks 5,000+ components and sections and 250+ page examples for React, styled with Tailwind CSS v4. One licence is a one-time $349 with lifetime updates; teams start at $999.

Get Untitled UI Pro

Untitled UI React. We may earn a commission, at no extra cost to you.

01. Tailwind SVG feTurbulence Noise Parameter Breakdown (opens in a new tab)

Published

Pure Tailwind
Every grain effect on the modern web comes out of one SVG primitive: <feTurbulence>. This is the parameter sheet for it — six live plates, each changing exactly one attribute, plus a zero-JS strength rail that re-tunes all six at once. The port's win is that the entire grain layer (content, inset, filter, blend mode, opacity) reads as one after: class list on the surface that owns it.

02. Tailwind baseFrequency and numOctaves Grain Size Control (opens in a new tab)

Published

Pure Tailwind
A specimen sheet for the only two attributes that decide whether grain reads as expensive film stock or as a broken JPEG: seven baseFrequency steps, a four-step octave ramp, the two-value anisotropic form, and the min-resolution: 2dppx correction almost nobody ships. The port's interesting problem is the blend mode — it has to differ per theme, so it stays a custom property read back through an arbitrary utility.

03. Tailwind Data URI SVG Noise Texture Without an Image Request (opens in a new tab)

Published

Pure Tailwind
The shippable form of browser-generated grain: the whole <feTurbulence> document folded into a URL-encoded data URI, parked in one custom property, and reused across a hero, three cards, two buttons and a footer. 382 bytes, zero network requests, and in v4 every surface reads it as bg-[image:var(--gtw03-noise),…] with the blend stack stated right beside it.

04. Tailwind Grain Opacity and mix-blend-mode Composite Matrix (opens in a new tab)

Published

Pure Tailwind
Grain has two dials after generation: how strong it is and how it composites. This is the full matrix — eight mix-blend-mode values against one identical noise layer, plus a five-stop opacity scale with the production band marked. The port deletes every inline style attribute the CSS version needed: each mode is a real utility, and isolate sits on the surface that owns the blend.

05. Tailwind Tinted SVG Noise with feColorMatrix (opens in a new tab)

Published

Pure Tailwind
Raw feTurbulence writes independent noise into red, green and blue, so untinted grain is colour confetti. feColorMatrix fixes it properly: flatten RGB to one hue, then move the texture into the alpha channel so the layer composites in normal blend mode over anything. Six named stocks, and the port's point is that the filter chain is the only part that cannot become a utility — so everything else does.

06. Tailwind Grain Paint Cost and Byte Size Measured Live (opens in a new tab)

Published

Tailwind + JS
Everyone repeats that SVG filters are expensive. Nobody says how expensive. This demo measures it live in your own browser: median frame time for four surfaces — no grain, cached data URI, live 5-octave filter, six blended layers — plus the real byte size of each texture token, read out of computed styles rather than estimated. The only demo in the collection with JavaScript, and it exists because the numbers have to be yours, not mine.
Newsletter

Enjoying these demos? Get new ones by email.

A short email when a new collection ships. Unsubscribe any time.

at

Almost there: check your inbox to confirm.Manage

07. Tailwind Anti-Banding Grainy CSS Gradient Hero (opens in a new tab)

Published

Pure Tailwind
Banding is not a bug in your gradient, it is the 8-bit display pipeline showing through — and the fix is the one film and print have used for a century: add noise. A full-bleed dusk hero interpolated in oklab, stopped through the dark third, dithered at 3.5%, plus a side-by-side of the same ramp treated and untreated.

08. Tailwind Vignette Photo Overlay with Film Grain (opens in a new tab)

Published

Pure Tailwind
A contact sheet of three frames, each with a lens vignette under a luminosity-blended grain layer and its own grain weight. No canvas, no image processing, no filters on the photograph — four ordinary layers over an <img>. The port's neat trick: the per-frame weight that needed an inline style attribute is now an arbitrary-property utility, [--gtw08-weight:0.13].

09. Tailwind Tactile Card Surface with Subtle Noise (opens in a new tab)

Published

Pure Tailwind
Six product cards, identical except for one thing: grain weight tied to elevation. A card that sits higher catches more light and shows more tooth, so its noise is stronger — and the sixth card, with zero grain and the same fill, shadow and radius, is the one that looks like plastic. Four to eight percent opacity is the entire difference between a surface and a rectangle.

10. Tailwind Full-Bleed Hero Section Noise Background (opens in a new tab)

Published

Pure Tailwind
A production hero: unedited photograph, colour wash, two grain scales, and a legibility scrim — five stacked layers, zero added requests. The fine grain gives the surface tooth, the coarse grain at a fifth of the frequency gives the frame weather, and the staggered reveal is a single @theme animation token applied as animate-gtw10-rise.

12. Tailwind Textured Button and Input Surfaces (opens in a new tab)

Published

Pure Tailwind
A control kit where every surface is a material: buttons are raised, inputs are recessed, and both carry the same grain token. Press a button and three things change at once — grain weight, highlight direction and shadow depth. The port's wins are active:after: for the pressed texture and peer-user-invalid: for validation copy that cannot drift from the field it describes.

13. Tailwind Textured Section Divider with SVG Grain (opens in a new tab)

Published

Pure Tailwind
Three ways for two sections to meet like materials rather than like divs: a torn edge driven by feDisplacementMap, a masked grain fade, and a hairline with a grain wash spilling past it. The continuity trick is the same in all three — the grain layer runs across the join at identical weight, which is what makes two bands read as one surface.

14. Tailwind Static Halftone Dot Print Effect (opens in a new tab)

Published

Pure Tailwind
A print halftone built from one radial-gradient tiled at a pitch, rotated to a screen angle, and blended over a high-contrast greyscale photograph. Three pitches on a specimen row, plus a two-ink duotone with its screens at 15° and 75° — thirty degrees apart, because that is what stops two dot grids from beating into moiré.
Newsletter

Enjoying these demos? Get new ones by email.

A short email when a new collection ships. Unsubscribe any time.

at

Almost there: check your inbox to confirm.Manage

15. Tailwind Dithered Bayer Matrix Shading Effect (opens in a new tab)

Published

Pure Tailwind
Ordered dithering, the 1984 way: sixteen dispersed threshold values in a 4×4 tile, blended in hard-light over a deliberately banded gradient. Your eye reassembles the dot pattern into a smooth ramp. Three matrix sizes set three eras, and the same layer turns photographs into one-bit images.

16. Tailwind Paper Stock and Letterpress Press Effect (opens in a new tab)

Published

Pure Tailwind
Letterpress in three parts: anisotropic fibre noise for the stock, a two-value text-shadow for the impression, and a deckle edge chewed by feDisplacementMap. One light source, declared once, shared by the type, the card edges and the paper itself — which is the only reason the effect is convincing.

17. Tailwind Risograph Print Misregistration Texture (opens in a new tab)

Published

Pure Tailwind
Risograph's charm is its failure mode: a paper feed that never lines up, so every colour lands a few millimetres off and the overlaps print as a third ink. Two offset ink layers, misregistered display type built from attr() pseudo-elements, and paper grain on top — four pixels of error, deliberately.

18. Tailwind Woven Fabric and Canvas Texture Surface (opens in a new tab)

Published

Pure Tailwind
Four upholstery fabrics — linen, canvas, hessian, denim — built from two crossed repeating-linear-gradients, a highlight pass and a turbulence slub layer. Under 500 bytes each, tiling perfectly by construction, and fully recolourable, which is the version that actually works in a product configurator where the customer picks the colour.

19. Tailwind Dark Mode Noise Without Muddy Shadows (opens in a new tab)

Published

Pure Tailwind
Grain gets ripped back out of dark products for one reason: overlay can only darken below mid-grey, so noise on a near-black surface turns elevation into mud. The fix is three parts — soft-light instead of overlay, roughly 1.6× the light-theme opacity, and a mask that keeps noise out of the deepest shadows. A dark dashboard shipping all three.

20. Tailwind Reduced Motion Static Grain Fallback (opens in a new tab)

Published

Pure Tailwind
Animated grain is the single most likely thing in a texture collection to make somebody feel ill — rapid luminance change across a large area is exactly the trigger for vestibular disorders, migraine and photosensitivity. This demo animates a film gate properly (compositor transforms, steps(8)), and then designs the reduced-motion version instead of switching the animation off.
FAQ

Frequently asked questions

How do I generate grain in the browser without loading a texture image?
Every demo here builds noise from one SVG primitive rather than a PNG. You write an <svg> containing <filter> with a <feTurbulence> node, apply that filter to a <feFlood> or a full-bleed rect, then fold the whole document into a background-image: url('data:image/svg+xml,...'). That is the shippable form shown in Demo 03 — zero extra network requests, because the grain is markup, not a file. The two attributes that matter are type (use fractalNoise for cloudy film grain, turbulence for harder marble veins) and baseFrequency. Demo 01 breaks down every input; Demo 02 is a specimen sheet so you can see the size change. Keep the SVG tiny and let CSS background-repeat tile it, rather than sizing the SVG to the viewport.
What does baseFrequency actually control, and why does my grain look like blurry blobs?
baseFrequency is the spatial frequency of the noise — how many times the pattern repeats per user unit. Low values like 0.3 produce large soft cloud-like blobs; high values like 0.9 produce a tight, film-stock speckle. The blurry-blob bug is almost always a value that is too low for the density you wanted, so each noise cell spans many pixels. Demo 02 lays out the full range side by side so you can pick by eye instead of guessing. The second dial is numOctaves: it stacks additional layers of finer detail on top, so 1 is smooth and 3 or 4 adds crunch. More octaves cost more paint time, so raise it only until the texture reads right. A common combination for a photographic grain is a high baseFrequency with two or three octaves, then knock the whole layer's opacity down.
Why is my SVG noise coming out coloured instead of neutral grey grain?
Raw <feTurbulence> writes independent random values into the red, green and blue channels, so every pixel gets three unrelated numbers and the result is confetti, not grain. To get neutral monochrome speckle you have to collapse the channels after generation. Demo 05 does this with <feColorMatrix>: use type="matrix" and route all three input channels into equal luminance, or use type="saturate" with a value of 0 to strip colour entirely. Once it is grey you can re-tint deliberately by biasing the matrix toward a single hue — warm the grain for film, cool it for a print look. This is also why blending matters: a coloured raw-turbulence layer set to overlay will shift the hue of everything beneath it, which reads as a bug rather than a texture. Desaturate first, tint second.
How do I stop banding in a CSS gradient hero without switching to an image?
Banding is not a flaw in your gradient — it is the 8-bit display pipeline quantising a smooth ramp into visible steps, and it shows up worst on large dark-to-mid gradients. Demo 07 fixes it the cheap way: lay a very faint grain layer over the gradient so the noise dithers the boundary between adjacent bands, and the eye integrates it back into a smooth transition. You do not need much — grain at a few percent opacity is enough to break the hard step edges. The key is that the noise must sit above the gradient in stacking order and composite over it, typically with mix-blend-mode: overlay so it lightens and darkens symmetrically around mid-grey. This keeps the whole hero as pure CSS, so it stays crisp at any viewport width and adds no image payload, unlike exporting a pre-dithered PNG that then has to be sized for every breakpoint.
How expensive is an SVG grain filter to paint, and when will it hurt performance?
SVG filters are repainted by the CPU, not composited on the GPU like a transform, so a full-viewport <feTurbulence> that re-rasterises every frame is the case to avoid. Demo 06 measures this live rather than repeating folklore. The safe pattern is a static grain: generate the noise once into a data-URI background so the browser rasterises a single tile and caches it — that is nearly free after first paint. Cost climbs when the filter is applied to a large live element, when numOctaves is high, and worst of all when the grain is animated by cycling baseFrequency or a seed each frame, which forces a fresh full-size rasterisation continuously. Keep the generated SVG small and tile it with background-repeat; reserve animated grain for small elements, and gate it behind the reduced-motion fallback in Demo 20.
In what order do I stack a hero's photo, colour wash, grain and text so it stays legible?
Demo 10 is a production hero built as five explicit layers, bottom to top: the unedited photograph, a colour wash to unify the palette, a coarse grain, a fine grain, and a legibility scrim directly under the text. The order is the whole trick. The wash sits over the photo so the image reads as one tone rather than a busy snapshot. Grain goes over the wash — Demo 11 shows why: put grain under a backdrop-filter: blur() glass panel and the blur averages the speckle straight back into smoothness, so texture over glass must be the top layer, not a buried one. Finally the scrim — a dark gradient or a semi-opaque fill — goes above the grain but below the copy, because if grain lands on top of the text it fights the letterforms. Manage this with stacking context, giving each layer its own element rather than piling everything into one background shorthand.
Grain looks great in light mode but turns my dark UI muddy — how do I fix that?
This is the number-one reason teams rip texture back out of dark products, and Demo 19 is built specifically for it. The cause is the blend mode: overlay lightens values above mid-grey and darkens values below it, so on a dark surface almost every pixel is on the darken side and the grain only ever muddies the shadows — it never adds the highlight sparkle that makes light-mode grain feel tactile. The fix is to swap the composite. Use soft-light for a gentler symmetric effect, or on very dark panels use screen so the grain can only lighten, adding texture without deepening the murk. Pair that with a lower opacity than you would use on white, because dark backgrounds show noise contrast more readily. Test the same tile on both themes rather than assuming one blend mode carries across — the demos deliberately show the same grain failing and then working after the mode change.
Is animated film grain an accessibility problem, and what should I ship instead?
Yes — animated grain is the single most likely thing in a texture collection to trigger discomfort, because rapid frame-to-frame luminance flicker across a wide area is exactly the pattern that provokes motion sensitivity and, at the wrong frequency, seizure risk. Demo 20 is the required fallback: wrap any moving grain in @media (prefers-reduced-motion: reduce) and swap it for a static tile — the texture stays, only the motion stops. Practically, that means the animated seed or shifting baseFrequency is the thing you disable, while the generated noise background remains painted. There is a performance dividend too, since the static tile no longer re-rasterises every frame. Treat this as non-negotiable rather than a nicety: default to static grain everywhere, and only opt an element into animation when it is small and the reduced-motion branch is already in place. A texture is decorative, so it must never be the thing that makes the page unusable.

Related collections

20 CSS 3D Effects preview

20 CSS 3D Effects

20 hand-coded CSS 3D patterns covering the transform pipeline reference build, the perspective property versus the perspective function, perspective-origin as the camera position, why transform function order changes the result, backface-visibility on two sided elements, what silently flattens preserve-3d, building a cube from six faces, transform-origin in three dimensions, translateZ versus scale for depth, z-fighting on coplanar surfaces, rotate3d and the transform matrix, plus ring layouts, stacked z-planes, pointer tilt with parallax, a hinged page-turn flipbook, a drag-rotate cube navigator, an extruded synth panel, perspective floor geometry, nested 3D contexts, and helix distribution. 14 demos are pure CSS; 6 use vanilla JavaScript.

22 CSS Brutalism preview

22 CSS Brutalism

22 hand-coded brutalist and neubrutalist CSS designs covering the full spectrum of the aesthetic — from the anti-design brutalism of 2014-2018 (raw system fonts, zero border radius, monochrome density, visible structure) through to the neubrutalism of 2021-present (bright pastel fills, thick black borders, hard offset shadows with zero blur, rounded blocks). The neubrutalist half ships SaaS pricing cards with sticker badges, a pastel admin dashboard, signup forms, rotated feature cards, an offset-shadow navbar, a playful button set, a native dialog modal, a testimonial wall, blog cards, chunky toggles, a landing hero, an image gallery, stats panels and a rounded footer. The brutalist half covers product grids, raw form controls, a monochrome data dashboard, a portfolio index, indie SaaS pricing, Windows 95 desktop chrome, editorial long-read and a streetwear catalog. Every design is scoped under a .brt-NN prefix for no-collision pasting, guards prefers-reduced-motion, and ports unchanged to React, Vue, Svelte, Astro, Next.js and Tailwind.

20 CSS Claymorphism preview

20 CSS Claymorphism

20 hand-coded CSS claymorphism designs covering the three-layer shadow recipe that defines the style, inner highlight and inner shadow layering, the border radius scale that makes shapes read as puffy rather than merely rounded, claymorphism compared side by side with neumorphism, a clay and glassmorphism hybrid, single light-source discipline across a layout, depth tiers for visual hierarchy, a Tailwind implementation with both arbitrary values and theme tokens, squishy button press states, toggles and checkboxes, inset input wells and search bars, badge and pill systems, cards, popover-based modals, pricing tables, mobile tab bars, app icon grids, toast and alert bubbles, dark mode shadow recalibration, and the paint cost of animating shadows. 19 demos are pure CSS; 1 uses vanilla JavaScript.

Search CodeFronts

Loading…