CSS CRT / SCANLINES / VHS GENERATOR

Build a retro CRT screen overlay with scanlines, vignette, and flicker, then copy the CSS.

No Signal
.crt {
  position: relative;
  overflow: hidden;
  border-radius: 22px;
  animation: crt-flicker 3s infinite;
}

.crt__tint {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: #3dff6a;
  mix-blend-mode: color;
  opacity: 0.6;
}

.crt::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background: repeating-linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0.35) 0px,
    rgba(0, 0, 0, 0.35) 1px,
    transparent 1px,
    transparent 3px
  );
}

.crt::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  background: radial-gradient(ellipse at center, transparent 65%, rgba(0, 0, 0, 0.85) 100%);
}

@keyframes crt-flicker {
  0%, 100% { opacity: 1; }
  8% { opacity: 0.8; }
  10% { opacity: 1; }
  50% { opacity: 1; }
  52% { opacity: 0.7; }
  54% { opacity: 1; }
  72% { opacity: 0.9; }
  74% { opacity: 1; }
}

How to build a CRT overlay effect

  1. 1

    Pick a phosphor tint: none, green, amber, or blue.

  2. 2

    Adjust scanline spacing, line opacity, and vignette strength on the live preview.

  3. 3

    Toggle flicker and curved corners for the full retro-screen look.

  4. 4

    Copy the CSS and layer it over any content with an absolutely positioned overlay.

Questions

How are the scanlines drawn without an image?
repeating-linear-gradient paints a thin semi-transparent black band followed by a transparent gap, over and over down the element — that's a scanline pattern. Changing the gap size (spacing) controls how tight or coarse the lines look, and the band's alpha controls how visible they are.
What creates the vignette effect?
A radial-gradient from transparent at the center to a dark, semi-opaque edge, stacked in a second pseudo-element above the scanlines. It darkens the corners the way a curved CRT tube or an old VHS transfer would, without touching the actual screen content underneath.
How do I put this over real content, like a video or image?
Wrap your content in a position: relative container with the .crt class, and the two overlay layers (::before for scanlines, ::after for the vignette) are position: absolute with pointer-events: none, so they sit on top visually without blocking clicks or interaction with what's underneath.
Will the flicker animation affect accessibility or motion-sensitive users?
It's a subtle, fast opacity flicker, but any animation can bother users with vestibular disorders. Wrap the animation rule in @media (prefers-reduced-motion: no-preference) in production, or leave Flicker off and ship the static overlay instead.
Does this tool store or upload anything?
No — every value is computed and rendered locally in your browser. Nothing about your settings or preview is sent to a server.