> ALIAS: THE GREY ONE
> ALIBI: NOT CHECKED
> LAST SEEN: 11:10 PM_
A cathode-ray monitor in pure CSS: green phosphor text on black, scanlines, darkened corners, and a slight dimming of the lines every 4 seconds.
Updated
This effect is free — the Distortion category contains 31 effects total, including 5 free. Effect.Labs has 840 vanilla effects. Explore the category →
Click to start, wait for green, then click again as fast as you can.
Servers in France, nightly backups, a human on the phone.
.crtm-monitor draws the screen: #0a0a0a background, 8 px grey frame with rounded corners, 280 px wide by default, and a green inner glow (box-shadow: inset). The text in .crtm-content uses Courier New, #33ff33 green, with an 8 px text-shadow that mimics phosphor afterglow.
Two pseudo-elements cover the screen without catching the mouse: ::before draws scanlines (2 px transparent, 2 px of 15 % black), ::after darkens the edges with a radial gradient (transparent up to 60 %, then 50 % black). That vignetting suggests a bulging tube; the picture is not actually curved.
Each text <span> follows the 4 s crtmFlicker animation: nothing for 92 % of the time, then opacity drops to 0.7, comes back, drops to 0.8 and returns to 1. The lines are real text, free to replace. No JavaScript; settings go through CSS variables.
#33ff33 green on #0a0a0a, a ratio of about 14:1, well above the AA threshold. The vignetting only darkens the corners.prefers-reduced-motion: reduce, the periodic dimming is switched off; the text stays on screen continuously.aria-live="polite" on the monitor so the change is announced.CSS only, no dependency. Gradients, inset box-shadow, animations and CSS variables have been everywhere for a long time; the most recent feature is prefers-reduced-motion (Chrome 74, Firefox 63, Safari 10.1, according to MDN data). Measured in Chromium 151, Firefox 153 and WebKit 26.5: same rendering, two independent copies, fluid width up to 100 %.
In a browser without prefers-reduced-motion, the dimming always plays, with no other consequence. Without CSS variables (very old browsers), the settings are ignored and the monitor keeps its default values.
Copy the two blocks (HTML and CSS) into your page. No JavaScript, no dependencies.
<div class="fx-0271-root">
<div class="crtm-monitor">
<div class="crtm-content">
<span>> SYSTEM BOOT OK</span><br>
<span>> LOADING DATA...</span><br>
<span>> READY_</span>
</div>
</div>
</div>
.fx-0271-root,.fx-0271-root *,.fx-0271-root *::before,.fx-0271-root *::after{box-sizing:border-box}
/* Settings (all optional, set them on .fx-0271-root or a parent):
--crtm-w monitor width (280px; 100% fills the parent)
--crtm-color phosphor color of the text (#33ff33)
--crtm-glow text glow (rgba(51,255,51,.6))
--crtm-size text size (14px)
--crtm-frame frame color (#2a2a2a)
--crtm-page / --crtm-root-h wrapper background and min height (rgb(10,10,15) / 280px) */
.fx-0271-root{display:flex;align-items:center;justify-content:center;width:100%;min-height:var(--crtm-root-h,280px);position:relative;background:var(--crtm-page,rgb(10,10,15));color:#fff;font-family:sans-serif}
.crtm-monitor{background:#0a0a0a;border:8px solid var(--crtm-frame,#2a2a2a);border-radius:20px;padding:24px;position:relative;overflow:hidden;width:var(--crtm-w,280px);max-width:100%;min-height:160px;box-shadow:inset 0 0 60px rgba(0,255,0,.1),0 0 20px rgba(0,0,0,.5)}
/* scanlines */
.crtm-monitor::before{content:"";position:absolute;top:0;left:0;width:100%;height:100%;background:repeating-linear-gradient(0deg,transparent,transparent 2px,rgba(0,0,0,.15) 2px,rgba(0,0,0,.15) 4px);pointer-events:none;z-index:2}
/* vignetting */
.crtm-monitor::after{content:"";position:absolute;top:0;left:0;width:100%;height:100%;background:radial-gradient(ellipse at center,transparent 60%,rgba(0,0,0,.5) 100%);pointer-events:none;z-index:3}
.crtm-content{color:var(--crtm-color,#33ff33);font-family:"Courier New",monospace;font-size:var(--crtm-size,14px);line-height:1.6;text-shadow:0 0 8px var(--crtm-glow,rgba(51,255,51,.6));position:relative;z-index:1}
/* every 4s the lines dim briefly, like an old tube */
.crtm-content span{animation:crtmFlicker 4s infinite}
@keyframes crtmFlicker{0%,to{opacity:1}92%{opacity:1}93%{opacity:.7}94%{opacity:1}96%{opacity:.8}97%{opacity:1}}
@media (prefers-reduced-motion:reduce){
.crtm-content span{animation:none}
}
Pure CSS — no JavaScript needed.
Options passed to the API or data-* attributes:
| Option / property | Default | Effect |
|---|---|---|
Width (CSS — --crtm-w) |
280 px | 100% fills the parent; the monitor never overflows its container (max-width: 100%). |
Text colour (CSS — --crtm-color) |
#33ff33 |
Amber #ffb000 for an orange terminal, bluish white #d8ecff for a colder screen. Match --crtm-glow too. |
Glow (CSS — --crtm-glow) |
rgba(51, 255, 51, .6) |
Colour of the 8 px halo around the letters; transparent gives crisp text without afterglow. |
Text size (CSS — --crtm-size) |
14 px | 11 px for a small widget, 18 px and up for a title screen. Line height stays at 1.6. |
Frame colour (CSS — --crtm-frame) |
#2a2a2a |
Beige #cfc6b0 for an old computer case, or your interface colour to blend the monitor into the page. |
Text lines (HTML — the <span> elements of .crtm-content) |
3 lines, separated by <br> |
Add or remove lines; every span dims together with the others. |
Demo frame (CSS — --crtm-page, --crtm-root-h) |
rgb(10, 10, 15), at least 280 px tall |
transparent and 0 drop the monitor into your page without the dark band around it. |
No. The sense of curvature comes from the vignetting (edges darkened by a radial gradient) and the rounded corners. The text is not distorted, which keeps it perfectly readable.
Replace the content of a <span> from a script (span.textContent = '> SCORE: 247'). Add aria-live="polite" on .crtm-monitor so screen readers announce the new value.
It is short and faint (0.7 opacity at its lowest), far from a blink. It stops by itself when the visitor asked for less motion, and you can remove it everywhere by deleting the animation rule on .crtm-content span.