Grain Overlay
A canvas grain overlay that flickers frame by frame, in fine / coarse / vintage textures, adding film-like noise to gradients and images.
npx shadcn@latest add https://webberui.com/r/grain-overlay.jsonPlayground
Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.
<GrainOverlay />
Installation
npx shadcn@latest add https://webberui.com/r/grain-overlay.jsonOr, once registries are configured in components.json, install it as @webberui/grain-overlay.
Usage
GrainOverlay is one absolutely positioned layer: drop it into any relative container and it covers the whole background. Adding isolate to the container keeps the blend mode confined to the container instead of bleeding through to the page behind it.
import { GrainOverlay } from "@/components/ui/grain-overlay";
<div className="relative isolate overflow-hidden rounded-xl bg-gradient-to-br from-indigo-500 to-pink-500">
<GrainOverlay variant="coarse" />
{/* your content */}
</div>Props
| Prop | Type | Default | Description |
|---|---|---|---|
variant | "fine" | "coarse" | "vintage" | "fine" | Grain texture preset; any parameter you do not override follows this preset |
intensity | number | Per variant | Overall opacity of the overlay (0–1) |
grainSize | number | Per variant | Edge length of a single grain (CSS px, integer) |
contrast | number | Per variant | Grain contrast (0–1) — the light/dark amplitude of each grain |
blendMode | GrainBlendMode | Per variant | Blend mode (overlay / soft-light and so on) |
fps | number | Per variant | Flicker update rate (1–60) |
animated | boolean | true | Whether to flicker frame by frame; when false it is a single static frame |
frameCount | number | 8 | Number of noise frames pre-generated and cycled (1–24) |
The defaults for the three variant presets: fine (grainSize 1, delicate and understated), coarse (grainSize 3, high contrast, rough), vintage (soft-light, slow flicker, imitating old film stock). Passing any numeric prop explicitly overrides that preset's value.
How it works
- The grain is drawn on canvas frame by frame:
frameCountindependent low-resolution grayscale noise frames are pre-generated, and each frame — throttled byfps— picks one at random and scales it up to fill the layer, producing a convincing film flicker. - Grain brightness is centered on mid-gray (128) with
contrastsetting the amplitude; paired with theoverlayblend mode, mid-gray leaves the underlying color untouched and only the light and dark grains are layered on. grainSizeis measured in CSS pixels, and image smoothing is turned off (blocky upscaling) to keep the grains sharp and consistently sized even on high-DPR displays.- Adjusting
intensityandblendModeis a pure styling change and does not rebuild the noise; only changes tograinSize,contrast,fps, and the like regenerate the frames. - A
ResizeObserverwatches the container size, and rebuilding the noise is debounced; the rAF, timers, and observers are all cleaned up on unmount.
Accessibility
- The overlay carries
aria-hiddenandpointer-events-none— decorative only, so it interferes with neither assistive technology nor interaction with the layer beneath. - When the user has "reduce motion" enabled at the system level, the frame-by-frame flicker stops automatically and a single static noise frame is rendered instead.
Beams Background
A canvas background of beams streaming continuously along a diagonal path, with palette, angle, glow, and cursor-driven acceleration.
Interactive Dot Grid
An interactive dot grid background — a full-bleed regular grid where dots near the cursor scale up and get pushed away, then ease smoothly back.