Dynamic Pixel Grid
A canvas grid of pixels that flicker random opacities inside a sine-pulsing circle — a breathing field of static. Themeable, DPR-crisp, reduced-motion aware. Based on Alex Krasikau.
Usage
import { PixelGrid } from "~/components/effects/pixel-grid";<PixelGrid size={360} color="hsl(0 0% 90%)" />// other mask shapes: "square" | "diamond" | "ring" | "full"<PixelGrid shape="diamond" density={0.15} />
How it works
It's a single <canvas> and a loop. The grid is ~100×100 little squares, and each one just stores an opacity. Every few frames, a slice of random cells (about 20%) gets bumped to a random opacity, and the rest hold their value. That alone reads as soft TV static.
The circle is what makes it feel alive. A radius breathes in and out on a Math.sin, and when a cell gets picked, it only lights up if it's inside that radius, otherwise it's snapped to zero. So the field of static swells and contracts. I made it themeable (the original drew black on white; this defaults to light pixels for dark backgrounds), scaled it for device pixel ratio so the squares stay crisp, and had it draw one still frame under prefers-reduced-motion.
// 100x100 cells; each tick, refresh ~20% of them to a random opacity.// Inside the pulsing circle they flicker; outside they go dark.const radius = baseR + amp * Math.sin(frame * 0.01);if (frame % 5 === 0) {const updates = Math.floor(count * density);for (let i = 0; i < updates; i++) {const x = (Math.random() * grid) | 0;const y = (Math.random() * grid) | 0;const dx = x * step + pixelSize / 2 - center;const dy = y * step + pixelSize / 2 - center;op[y * grid + x] =dx * dx + dy * dy <= radius * radius? Math.random() * 0.6 + 0.2: 0;}}
Props
| prop | type | default | description |
|---|---|---|---|
| size | number | 360 | Canvas size in px (square). |
| pixelSize | number | 4 | Pixel side length. |
| gap | number | 4 | Gap between pixels. |
| color | string | "hsl(0 0% 90%)" | Any CSS color. |
| density | number | 0.2 | Fraction of pixels refreshed each tick. |
| shape | "circle" | "square" | "diamond" | "ring" | "full" | "circle" | Mask the flicker to a sine-pulsing shape. |
Original by Alex Krasikau.