25 CSS Spinners21 / 25

Pure CSSMIT licensed

Retro TV Static Noise Loader

A miniature CRT television screen filled with flickering monochrome pixel tiles simulates analog static noise, complete with scanline overlay and vignette darkening.

Published

Live Demo
Try it

This is a full-page demo — interact inside the frame above, or open it in the playground for the full-screen experience.

The code

<div class="sp-21">
  <div class="sp-21__tv">
    <div class="sp-21__static">
      <div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div>
      <div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div>
      <div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div>
      <div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div>
      <div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div>
      <div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div>
      <div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div>
      <div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div>
      <div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div>
    </div>
    <div class="sp-21__scanline"></div>
    <div class="sp-21__glow"></div>
  </div>
</div>
.sp-21,
.sp-21 *,
.sp-21 *::before,
.sp-21 *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.sp-21 {
  --bg: #0a0a0a;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  background: var(--bg);
}

.sp-21__tv {
  position: relative;
  width: 120px;
  height: 90px;
  background: #111;
  border-radius: 8px;
  border: 3px solid #333;
  overflow: hidden;
  box-shadow: 0 0 20px rgba(0,0,0,0.8),inset 0 0 10px rgba(0,0,0,0.5);
}

.sp-21__static {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-columns: repeat(12,1fr);
  grid-template-rows: repeat(9,1fr);
  gap: 0;
}

.sp-21__pixel {
  background: #fff;
  animation: sp-21-flicker 0.08s steps(1) infinite;
}

.sp-21__pixel:nth-child(4n+1) {
  animation-delay: 0s;
  opacity: 0.9;
}

.sp-21__pixel:nth-child(4n+2) {
  animation-delay: 0.02s;
  opacity: 0.4;
}

.sp-21__pixel:nth-child(4n+3) {
  animation-delay: 0.04s;
  opacity: 0.7;
}

.sp-21__pixel:nth-child(4n) {
  animation-delay: 0.06s;
  opacity: 0.2;
}

.sp-21__pixel:nth-child(7n) {
  animation-duration: 0.12s;
}

.sp-21__pixel:nth-child(11n) {
  animation-duration: 0.06s;
}

.sp-21__pixel:nth-child(3n) {
  background: #888;
}

.sp-21__scanline {
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(
      to bottom,
      transparent 0px,
      transparent 3px,
      rgba(0,0,0,0.3) 3px,
      rgba(0,0,0,0.3) 4px
    );
  pointer-events: none;
}

.sp-21__glow {
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse,transparent 40%,rgba(0,0,0,0.5) 100%);
  pointer-events: none;
}

@keyframes sp-21-flicker {
  0%,
    100% {
    opacity: var(--o,0.9);
  }

  50% {
    opacity: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .sp-21__pixel {
    animation: none;
  }
}
Paste this into ChatGPT, Claude, Cursor, or any coding assistant. The block below is pre-framed with everything the AI needs to integrate this demo into your project — markup, styles, scoping notes, and the source URL. Hit Copy and paste straight into your chat.
Here's a working CSS Spinner from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Retro TV Static Noise Loader
Source: https://codefronts.com/motion/css-spinner-designs/retro-tv-static-noise-loader/

A miniature CRT television screen filled with flickering monochrome pixel tiles simulates analog static noise, complete with scanline overlay and vignette darkening.
## HTML
```html
<div class="sp-21">
  <div class="sp-21__tv">
    <div class="sp-21__static">
      <div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div>
      <div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div>
      <div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div>
      <div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div>
      <div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div>
      <div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div>
      <div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div>
      <div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div>
      <div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div><div class="sp-21__pixel"></div>
    </div>
    <div class="sp-21__scanline"></div>
    <div class="sp-21__glow"></div>
  </div>
</div>
```
## CSS
```css
.sp-21,
.sp-21 *,
.sp-21 *::before,
.sp-21 *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.sp-21 {
  --bg: #0a0a0a;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  background: var(--bg);
}

.sp-21__tv {
  position: relative;
  width: 120px;
  height: 90px;
  background: #111;
  border-radius: 8px;
  border: 3px solid #333;
  overflow: hidden;
  box-shadow: 0 0 20px rgba(0,0,0,0.8),inset 0 0 10px rgba(0,0,0,0.5);
}

.sp-21__static {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-columns: repeat(12,1fr);
  grid-template-rows: repeat(9,1fr);
  gap: 0;
}

.sp-21__pixel {
  background: #fff;
  animation: sp-21-flicker 0.08s steps(1) infinite;
}

.sp-21__pixel:nth-child(4n+1) {
  animation-delay: 0s;
  opacity: 0.9;
}

.sp-21__pixel:nth-child(4n+2) {
  animation-delay: 0.02s;
  opacity: 0.4;
}

.sp-21__pixel:nth-child(4n+3) {
  animation-delay: 0.04s;
  opacity: 0.7;
}

.sp-21__pixel:nth-child(4n) {
  animation-delay: 0.06s;
  opacity: 0.2;
}

.sp-21__pixel:nth-child(7n) {
  animation-duration: 0.12s;
}

.sp-21__pixel:nth-child(11n) {
  animation-duration: 0.06s;
}

.sp-21__pixel:nth-child(3n) {
  background: #888;
}

.sp-21__scanline {
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(
      to bottom,
      transparent 0px,
      transparent 3px,
      rgba(0,0,0,0.3) 3px,
      rgba(0,0,0,0.3) 4px
    );
  pointer-events: none;
}

.sp-21__glow {
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse,transparent 40%,rgba(0,0,0,0.5) 100%);
  pointer-events: none;
}

@keyframes sp-21-flicker {
  0%,
    100% {
    opacity: var(--o,0.9);
  }

  50% {
    opacity: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .sp-21__pixel {
    animation: none;
  }
}
```

How this works

A 12×9 grid of small div elements fills the TV screen area. Each cell runs sp-21-flicker — a very fast 0.08s steps(1) animation that snaps opacity between the cell's base value and zero. The steps(1) timing ensures a binary on/off flicker with no interpolation, exactly like analog noise. Four groups of cells (via 4n+1 through 4n) share different base opacities (0.9, 0.4, 0.7, 0.2) and delays, creating varied intensity across the grid.

Two overlay divs add the CRT effect: a repeating linear-gradient scanline pattern at 4px intervals, and a radial vignette gradient darkening the corners. The TV outer frame uses a subtle inset box-shadow for the recessed screen bezel look.

Make it yours

  • Change the noise colour from white/grey to green by setting --c:#00ff41 and --dim:#003b10 for a classic night-vision monitor look.
  • Increase the grid to 16×12 columns/rows and reduce cell size proportionally for finer, more realistic noise grain.
  • Add a CSS animation on the entire .sp-21__tv that occasionally shifts translateX by 2-3px for a signal distortion effect.
  • Remove the scanline overlay div and replace the background:#fff cells with background:var(--c) to create a coloured noise channel.
  • Add a filter:contrast(1.5) brightness(0.8) on the TV element to punch up the noise contrast.

Gotchas — read before shipping

  • steps(1) at 0.08s creates very frequent repaint events — 108 grid cells each repainting independently can easily overwhelm the paint budget on mobile; reduce cell count or increase animation duration for mobile-first contexts.
  • The animation-duration variation via 7n and 11n selectors only works as intended when those indices exist in the DOM; the grid must have enough cells for the pattern to be visible.
  • opacity animations create stacking context changes at the composited layer level — 108 simultaneous stacking context creations may cause rendering lag; consider Canvas or WebGL for high-quality static noise at scale.

Browser support

ChromeSafariFirefoxEdge
60+12+60+60+

CSS grid and steps() timing widely supported; performance-sensitive on mobile — test cell count.

Techniques used in this demo

Search CodeFronts

Loading…