Static Noise
TV snow with no antenna drawn on a canvas, scanlines, a sliding bar and a crackling “NO SIGNAL”: the dead-channel screen, down to the pixel.
Updated
This effect is part of Effect.Labs — 840 vanilla effects, some free, some premium. Distortion has 31 effects, including 5 free. Explore the category →
3 usage examples



How it works
The .tvn-screen (280×180 px, #0a0a0a background, 8 px corners) stacks four layers. At the bottom, the .tvn-canvas: on every frame the script gives each of its pixels a random grey, then shows it at 40% opacity. Above it, .tvn-lines draws a dark line every 2 px, and .tvn-bar, a 3 px light stroke, slides from top to bottom in 0.5 s. Last, the .tvn-text (“NO SIGNAL”, monospaced) carries a white glow plus red and cyan offsets, and wavers slightly (opacity 0.95 to 1 every 0.1 s).
The canvas takes the screen's size times the display density (capped at 2): the snow stays fine on a Retina display. A ResizeObserver resizes it whenever the screen changes size. The snow is redrawn at most 60 times per second (data-fps), even on a 120 Hz display, and not at all when the screen is out of view or the tab hidden (measured: 0 frames computed in 2 s off screen).
Each .tvn-screen has its own canvas and its own loop: two copies on a page snow independently (measured in Chromium 151, Firefox 153 and WebKit 26.5). The draw uses a small fast generator (xorshift) instead of Math.random(), to keep the pace on large screens.
An element placed in .tvn-screen with no position (neither absolute nor relative) is painted under the snow: the --tvn-opacity variable then sets how scrambled it looks. The escape game example does exactly that.
Accessibility
- Reduced motion: under
prefers-reduced-motion: reduce, the snow is drawn once and stays still, the scan bar is hidden and the text stops wavering. The “no signal” screen remains readable as it is. - Photosensitivity: the snow changes every frame, but pixel by pixel: the average brightness stays constant, no area flashes (frame-by-frame measurement, well below the WCAG 2.3.1 threshold). The text waver never exceeds 5% opacity.
- Screen readers: canvas, lines and bar carry
aria-hidden="true"; only the.tvn-texttext is read. Write a useful sentence there (“Episode available Friday”) rather than a bare “NO SIGNAL” if the screen carries information. - Click and touch: every layer has
pointer-events: none; the effect intercepts nothing.
Browser compatibility
Canvas 2D (putImageData), CSS variables, inset and 2 KB of JavaScript. Minimum version set by inset according to MDN data (Chrome 87, Firefox 66, Safari 14.1). ResizeObserver and IntersectionObserver are checked before use. Measured in Chromium 151, Firefox 153 and WebKit 26.5, and at density 2 (canvas twice as fine).
Without JavaScript, the screen stays black with its lines, bar and text: no snow. Without ResizeObserver, the canvas only follows window resizes.
The code
HTML structure to paste into your page (the CSS + JS come with your purchase):
<div class="fx-0260-root">
<div class="tvn-screen" data-fps="60">
<canvas class="tvn-canvas" aria-hidden="true"></canvas>
<div class="tvn-lines" aria-hidden="true"></div>
<div class="tvn-bar" aria-hidden="true"></div>
<span class="tvn-text">…</span>
</div>
</div>
One-time payment, no subscription — the code is yours forever
Customize
Options passed to the API or data-* attributes:
| Option / property | Default | Effect |
|---|---|---|
--tvn-w / --tvn-h |
280px / 180px |
Screen size; the canvas follows. 100% fills the container (give the root a height with --tvn-root-h). |
--tvn-opacity |
.4 |
Snow density. Around .9 it covers whatever lies underneath; around .1 it is just a veil. |
data-fps (on .tvn-screen) |
60 (1 to 60) |
Snow draws per second. 20–30 is plenty for a small thumbnail and spares phones. |
--tvn-bg |
#0a0a0a |
Screen background, seen between the specks. |
--tvn-text-size |
1.2rem |
Size of the .tvn-text, to shrink inside a thumbnail. |
--tvn-radius |
8px |
Corner radius of the screen. |
--tvn-root-bg / --tvn-root-h |
#0a0a0f / 300px |
Background and minimum height of the root; transparent and 0 to blend it into your layout. |
Text (HTML — .tvn-text) |
“NO SIGNAL” | Replace it with your message, or delete the tag for silent snow. |
FAQ
data-fps to 30: the snow stays convincing. Off screen, nothing is computed.hidden) when loading starts and hide it at the end. Hidden, it computes nothing; shown, it sizes itself and snows straight away. That is how the zapping example works.pixels[i] = 0xff000000 | gray << 16 | gray << 8 | gray writes the same grey into all three channels. For bluish snow, keep blue full and reduce the others, for example (gray >> 1) << 8 | (gray >> 1) for green and red.