shadcn.io is not affiliated with official shadcn/ui
Light Leak Shader draws the light leaks at the end of a roll of film. Blooms of red and orange, and with a third source a soft magenta, bleed in from the left and top edges of a near-black frame, swell until their cores burn to cream, and fade again, never more than two at once. Each leak is a soft glow stretched along its edge, warped by slow noise and streaked like light slipping between the layers of the film; the exposures add up in linear light, run through a filmic tone curve, and get a faint halation rim and fine grain that re-rolls 24 times a second. A WGSL fragment shader on WebGPU draws every pixel each frame.
Use it behind a portfolio, a photographer's or filmmaker's site, a festival page or an album launch: anywhere a warm, analog mood fits better than clean gradients. For grain alone, in plain CSS, use the Grain background; for warm light falling through cloud, Cloud Rays Shader. It runs only while it's on screen, holds a still frame with reduced motion, and shows a CSS gradient of the same leaks in browsers without WebGPU.
Installation
Usage
import { LightLeakShader } from "@/components/ui/light-leak-shader";<LightLeakShader className="flex min-h-[32rem] items-center justify-center">
<h1 className="text-5xl font-semibold text-white">Ship faster</h1>
</LightLeakShader>Light Leak Shader is a container: your content sits on top of the frame, in normal flow. It fills its own box, so give it a height or content. For a backdrop behind the whole page, render it empty with className="fixed inset-0 -z-10". The frame is near-black and the leaks stay near the left and top edges, so white text reads in both color schemes: in the middle of the frame it stays above 16:1 nineteen times out of twenty, and never drops below 4.2:1. Keep copy away from the left and top edges, where a leak burns to cream.
Demos
Cyanotype
A light backgroundColor switches the leaks from light to stain: instead of adding light, they multiply the frame by their color, like dye on paper. Here leakColor="#2fd3ff" stains the edges cyan and glowColor="#8a5cff" deepens to violet where the exposure is strongest, on cream. hotColor, the burnt-out cream, only shows on a dark frame.
In a card
The leaks scale with the box's height, so they stay in proportion on a small surface. leaks={3} adds the third, magenta-leaning source on the lower left, so something is always swelling. The leaks take turns: never more than two show at once, and a new one starts at most every 2.3 seconds.
Performance
About 0.3 ms of GPU time a frame at 1280×720 on an M2 Max laptop; slower GPUs take several times longer. The leaks are soft, so quality={0.5} hides well, but it makes the grain coarser. The animation stops when the shader scrolls out of view, and the browser pauses it in a hidden tab. Every shader on a page shares one GPU device and one frame loop, and vgpu (about 50 KB gzipped) loads only when the first one mounts.
Browser support
The shader needs WebGPU: Chrome and Edge, Safari 26 and later, and Firefox on Windows and macOS. Elsewhere, and until the first frame, the box shows a CSS gradient of the same leaks, which follows your color props, so the layout never jumps. data-state on the root reads unsupported there, if you want to style around it. See Shader Canvas.
Accessibility
The leaks are decoration: they're hidden from assistive tech and let every click through to your content. With reduced motion the shader draws one still frame, an orange leak along the top and a red one rising on the left, and stops. Nothing flashes: a leak swells over 1.3 to 1.8 seconds and fades over 2.7 to 3.6, and the grain moves each pixel's brightness by a few percent at most. White text in the middle of the frame stayed above 4.2:1 in every render we measured; near the left and top edges, a leak's core can burn to cream behind it.
FAQ
Can I change the colors?
Yes. leakColor is a leak's edge, glowColor its warm middle, hotColor the cream it burns to, and backgroundColor the frame. They take any CSS color, var(--primary) included, and follow a theme switch. On a light backgroundColor the leaks become stains in leakColor and glowColor, as in the cyanotype demo.
How do I get more or fewer leaks?
leaks sets how many sources take turns, from 1 to 3: one on the left, one on the top, and a third, magenta-leaning one lower on the left. With one, the frame rests dark between swells; with three, something is always glowing, but never more than two leaks show at once.
How do I make the leaks stronger or subtler?
intensity is the exposure: lower keeps the leaks dimmer and redder, close to the edges; 2 burns them to cream and lets them reach further into the frame. grain sets the film grain, from 0 (clean) to 1 (coarse).
How do I make it faster or slower?
speed scales time: at 1 each source swells every 7 seconds, at 0.5 every 14. paused holds the frame, and time draws one fixed moment, in seconds, which is handy for a poster.
Will it slow my page down?
It costs about 0.3 ms of GPU time a frame at 1280×720 on a laptop, and the CPU only sets a few numbers each frame. It stops when it's off screen. On a slow GPU or a large screen, quality={0.5} renders a quarter of the pixels; the leaks look the same and the grain gets a little coarser.
API Reference
LightLeakShader
data-slot="light-leak-shader"
backgroundColor?string
The frame behind the leaks. A light one turns the leaks into stains that tint it. Any CSS colour. @default "#0d0a09".
- Default
"#0d0a09"
fallback?string
What shows until the first frame and in browsers without WebGPU: a CSS
background value (gradients, sizes, a colour) that looks like the
shader. It can use the colour props' --shader-<field> variables.
glowColor?string
The warm middle of a leak, between its edge and its burnt-out core. Any CSS colour. @default "#ff9a3c".
- Default
"#ff9a3c"
grain?number
Film grain, from 0 (clean) to 1 (coarse). @default 0.35.
- Default
0.35
hotColor?string
The hottest part of a leak, where it burns out. Any CSS colour. @default "#fff1d6".
- Default
"#fff1d6"
intensity?number
Exposure, from 0 (no leaks) to 2 (burnt out): how far the leaks reach and how hot they get. @default 1.
- Default
1
interactive?boolean
Whether u.pointer follows the pointer. @default false.
leakColor?string
The leak's edge colour, where it first bleeds into the frame. Any CSS colour. @default "#ff4d1a".
- Default
"#ff4d1a"
leaks?number
How many leak sources take turns, from 1 to 3. Never more than two show at once. @default 2.
- Default
2
paused?boolean
Holds the current frame. @default false.
quality?number
Render scale, from 0.25 to 1, of the screen's pixels (capped at 2×). @default 1.
speed?number
Animation speed: 1 is normal, 0 holds the frame. @default 1.
time?number
A fixed moment, in seconds: draws it and doesn't animate.
render?ReactElement | ((props: object, state: object) => ReactElement)
Replace the host element or compose it with another component.
- Type
ReactElement | ((props: object, state: object) => ReactElement)
className?string
Forwarded to the part.
Related
- Pro


Cloud Rays Shader
Light & glassWarm light falling through cloud
- Pro


Pixel Sort Shader
Digital & retroGlitch art round a warm dusk
- Pro


CRT Phosphor Shader
Digital & retroA warm synth sunset on an old screen


Dither Gradient Shader
Digital & retroWarm paper and drifting orbs, as 1-bit, free
- Pro


Embers Shader
Ink, smoke & fireWarm glow in the dark, as coals
- Pro


CMYK Halftone Shader
Digital & retroPrint texture for an editorial page