Scanline CRT
CRT scanlines, aperture grille and tube curvature. Install with npx remotion-ui@latest add scanline-crt.
PrimitivePrimitives
$ npx remotion-ui@latest add scanline-crtPut the picture back inside a tube.
import { ScanlineCrt } from "@/remotion/primitives/scanline-crt";
<ScanlineCrt curvature={0.6}>
<YourScene />
</ScanlineCrt>Pass children to put content inside the tube, or drop it over a stack as a
bare overlay — it paints no plate of its own either way.
Four overlays that only work together
Bowed scanlines for the tube, a fine RGB grille for the phosphor mask, a rolling refresh bar for the shot-a-monitor look, and per-frame flicker for the mains hum. Take away the flicker and it reads as a static texture, which is the failure mode of every CSS CRT filter.
The flicker is a slow hum plus a per-frame jitter. The hum is what stops it reading as random noise; the jitter is what stops the hum reading as a fade.
Curvature is drawn
Each scanline is a quadratic whose midpoint is pushed away from the centre of the tube in proportion to its distance from it, so lines near the top bow up and lines near the bottom bow down. That read — glass, not glass-effect — arrives long before any corner shading does.
Content underneath is not geometrically warped. Warping a live subtree needs a displacement map per frame and costs far more than the effect is worth; the bowed lines plus the rounded tube face carry it.
Give it a picture
Every overlay here works by removing light: scanlines darken, the grille masks,
the vignette shades. Over a near-black plate the whole component is invisible.
If your tile looks empty, the tube has nothing to show — that is the first thing
to check, not intensity.
Stacking
For emulsion rather than phosphor, reach for animated-noise-grain. The two
stack, and grain over a CRT is exactly what a camera pointed at a monitor
produces.
Curvature is drawn: each scanline is a quadratic whose midpoint is pushed away from the tube centre, so lines bow up at the top and down at the bottom. Content underneath is not geometrically warped. Every overlay here removes light, so over a near-black plate the component is invisible — give it a picture.
Agent notes
Install first, then import the copied source component locally. AI guide →
@/remotion/primitives/scanline-crt- Use when: frame-level motion primitives and reusable animation wrappers.
- Customize: lineCount, lineOpacity, lineWidth, curvature, plus copied source for timing, layout, colors, and typography.
- Rule: do not import this component from the
remotion-uinpm package; it is copied into your project.
Usage
import { ScanlineCrt } from "@/remotion/primitives/scanline-crt";
<ScanlineCrt curvature={0.6}>
<YourScene />
</ScanlineCrt>API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
| children | ReactNode | - | What the tube is showing. Omit to use it as a bare overlay. |
| lineCount | number | 90 | How many scanlines across the frame. |
| lineOpacity | number | 0.34 | Darkness of a scanline. |
| lineWidth | number | 1.6 | Scanline weight in px, independent of output size. |
| curvature | number | 0.55 | How hard the tube face bows. 0 draws dead straight lines. |
| cornerRadius | number | 22 | Corner radius of the tube face, in px. |
| rollInFrames | number | 96 | Frames for the refresh bar to cross. 0 removes it. |
| rollOpacity | number | 0.16 | Brightness of the refresh bar. |
| flicker | number | 0.05 | Frame-to-frame brightness jitter. |
| grille | number | 0.22 | Strength of the RGB aperture grille. |
| vignette | number | 0.55 | Corner darkening. |
| tint | string | "transparent" | Phosphor tint over the picture. |
| tintBlend | CSS mix-blend-mode | "overlay" | How the tint composites. |
| intensity | number | 1 | Strength of every overlay at once. |