Distortion✨ Premium

Retro Terminal

A terminal window whose green lines reveal themselves one after another, once, before a solid cursor starts blinking. All in CSS.

CSSAnimationTerminal

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

3D printer log after "Start printing" — Retro Terminal example 1

① 3D printer log after "Start printing"

WhenOn a workshop dashboard, the part card (spiral vase, PLA, 2 h 14 min) has a "Start printing" button. On click, the printer log appears and types its steps: command, nozzle heating, bed, first layer.
WhyLine-by-line typing shows that the machine is working and in which order; users see their action taken into account without a generic loading box.
Settings--rtm-w: 100%, --rtm-line-time: .45s, --rtm-size: 11px, five lines. The click only shows the root (hidden before): typing then starts from the first line.
Log book of a text-based survival game — Retro Terminal example 2

② Log book of a text-based survival game

WhenA text adventure fills the screen: the day 12 log types itself line after line (supplies, weather, smoke in the distance), then the cursor waits for the player's choice, made with the buttons below.
WhyThe typing rhythm builds the story's suspense: each piece of information arrives in turn, and the final cursor says "your move".
Settings--rtm-w: 100%, window at height: 100%, --rtm-line-time: .38s, --rtm-size: 14.5px, six lines (the most handled without a per-line setting). Status bar and action buttons added by the scene, outside the root.
Go-live step at the foot of a project card — Retro Terminal example 3

③ Go-live step at the foot of a project card

WhenIn an agency's project board, the card of the site being published has a three-line mini terminal at its foot: command, checks, upload in progress with the cursor. The other cards have a plain "Live" or "Mock-up" tag.
WhyShrunk to 9.5 px, the terminal becomes a telling status indicator for a technical team: the exact step reads at a glance, and the blinking cursor shows the job is not done.
Settings--rtm-w: 100% of the card, --rtm-size: 9.5px, --rtm-line-time: .5s; the scene shrinks the bar (6 px dots) and the inner padding.

How it works

.rtm-window draws the window: a top bar with three dots (red, yellow, green), a black body in Courier New, thin scanlines laid by .rtm-body::before. Each .rtm-line is #3f3 green, 12 px, with a 5 px halo.

A line that also carries the rtm-typing class starts at zero width (width: 0; overflow: hidden; white-space: nowrap). The rtmTyping animation widens it to 100 % in 30 steps (steps(30)) over --rtm-line-time (2 s by default): the text appears in jolts, as if typed. Each line waits for its turn: animation-delay is --rtm-i × --rtm-line-time, with --rtm-i set from 0 to 5 on the first six lines. The animation plays once and keeps its final state.

The .rtm-cursor block on the last line then blinks forever (0.8 s, stepped). Typing starts when the window is rendered: on page load, or when you show it (an element going from display: none to visible replays its CSS animations). No JavaScript.

Accessibility

  • Text present from the start: the lines exist in the HTML; only their visible width is animated. A screen reader reads all the text at once, without waiting for the typing.
  • Decorative parts hidden: the dotted bar and the cursor have aria-hidden="true".
  • Reduced motion: under prefers-reduced-motion: reduce, every line shows at once and the cursor stays lit, without blinking.
  • No interaction: the terminal is not an input field and adds no focusable element. The cursor does not invite typing: avoid it where visitors might think they can write.

Browser compatibility

CSS only, no dependency. Each line's delay is computed with calc() and CSS variables (Chrome 49, Firefox 31, Safari 9.1 according to MDN data); the most recent property is inset (Chrome 87, Firefox 66, Safari 14.1). Measured in Chromium 151, Firefox 153 and WebKit 26.5: at 2.5 s, first line complete, second in progress, the rest empty, in all three engines; two independent copies; all text visible with reduced motion.

Chrome 87+✓ Full (measured)
Firefox 66+✓ Full (measured)
Safari 14.1+✓ Full (measured in WebKit)
Edge 87+✓ Full
Mobile iOS 14.5+✓ Full
Android Chrome 87+✓ Full

Without CSS animations, the lines would stay at zero width: that is why the reduced-motion rule resets them to width: auto. Where the text must be read without delay, simply remove the rtm-typing class from those lines.

The code

HTML structure to paste into your page (the CSS + JS come with your purchase):

index.html — structure
<div class="fx-0276-root">
  <div class="rtm-window">
    <div class="rtm-header" aria-hidden="true">
      <span class="rtm-dot rtm-red"></span>
      <span class="rtm-dot rtm-yellow"></span>
      <span class="rtm-dot rtm-green"></span>
    </div>
    <div class="rtm-body">
      <div class="rtm-line rtm-typing">user@retro:~$ npm install nostalgia</div>
      <div class="rtm-line rtm-typing">Installing packages...</div>
      <div class="rtm-line rtm-typing">Done in 3.14s</div>
      <div class="rtm-line rtm-typing">user@retro:~$ <span class="rtm-cursor" aria-hidden="true"></span></div>
    </div>
  </div>
</div>

One-time payment, no subscription — the code is yours forever

Customize

Options passed to the API or data-* attributes:

Option / propertyDefaultEffect
Lines (HTML — <div class="rtm-line rtm-typing">) 4 lines Up to 6 lines follow one another on their own. Beyond that, give the line its rank: style="--rtm-i: 6". Without rtm-typing, a line shows immediately.
Time per line (CSS — --rtm-line-time) 2 s 0.4 to 0.6 s for a brisk log; the value is also the gap between two lines.
Width (CSS — --rtm-w) 280 px 100% fills the parent. Typing widens each line up to the terminal width: a wide window reveals short lines faster.
Colours (CSS — --rtm-color, --rtm-glow) #3f3, halo rgba(51, 255, 51, .5) The cursor follows --rtm-color. Amber #ffb000 or off-white change the era it evokes.
Text size (CSS — --rtm-size) 12 px 9 to 10 px in a small component, 14 px and up full screen.
Replay the typing (HTML/JS — showing the root) Once, on first render Switch the root from display: none to visible, or replace it with a copy (root.replaceWith(root.cloneNode(true))): the animations start over.
Demo frame (CSS — --rtm-page, --rtm-root-h) #0a0a0f, at least 300 px tall transparent and 0 drop the window into your layout.

FAQ

Not exactly: the line's visible width grows in 30 steps, whatever its length. A short line in a wide window is therefore revealed in fewer visible steps than a long one. The typing feel is there, without JavaScript.
Yes: add a <div class="rtm-line rtm-typing"> inside .rtm-body with style="--rtm-i: 0"; it types as soon as it is inserted. Add aria-live="polite" on .rtm-body so new lines are announced.
The complete terminal, every line shown, cursor lit and still. Nothing is missing: only the typing staging is removed.