Typewriter Variable
Reveals monospace text letter by letter using the Recursive variable font and a blinking cursor — pure CSS, zero JavaScript.
You'll get access to the interactive demo with a free account.
This effect is part of Effect.Labs — 811 vanilla effects, some free, some premium. Text has 56 effects, including 4 free. Explore the category →
3 usage examples



How it works
The text is fully written in the DOM but hidden behind overflow: hidden; white-space: nowrap. The vfType animation steps the width from 0 to 280px in steps(20) — 20 equal discrete jumps — visually simulating character-by-character reveal. The 50%–80% pause keeps the text visible before erasing, then the cycle repeats indefinitely.
The cursor is the element's own border-right: 2px solid. The vfBlink animation toggles the border color to transparent at 50% with step-end timing — no fade, hard jump — exactly reproducing a classic terminal cursor blink.
The Recursive font is a variable font: the axis "MONO" 1 switches its type engine to strict monospace spacing (every glyph at identical width). This is what makes the steps() technique convincing — each width jump matches exactly one character. The "CASL" (cursiveness) and "wght" (weight) axes are available to vary the style without changing the font.
Context lines (.vf-typewriter-line) use the same Recursive Mono at 0.75rem and 30% opacity — they represent previous and upcoming terminal commands, providing context without drawing attention. The whole scene is centered with vertical flexbox.
Accessibility
- prefers-reduced-motion: ABSENT from the code — the typing animation and cursor blink run even when the OS signals
reduce. To fix, add:@media (prefers-reduced-motion: reduce) { .vf-typewriter-text { animation: none; width: 280px; border-right: none; } } - Text is directly in the DOM (native
<span>) — screen readers read it without obstacle, noaria-hiddenor canvas involved. - Contrast:
#10b981(Emerald green) on#0a0a0fbackground → ratio ≈ 8.5:1, WCAG AAA level (normal text). Verify the ratio if you change the color. - No keyboard interaction required — the effect is purely decorative, nothing focusable.
- The HTML structure carries no
roleoraria-label. For hero use, addrole="img" aria-label="Terminal animation"to the container.
Browser compatibility
Requires CSS animation, steps(), and font-variation-settings — available in all browsers that support variable fonts.
If Recursive is unavailable, the browser falls back to the system <code>monospace</code> font (Courier New, Consolas…). The animation still works; the visual rendering changes slightly. Without <code>font-variation-settings</code> support, Recursive displays in its default static style.
The code
HTML structure to paste into your page (CSS + JS available with a premium account):
<div class="vf-preview">
<div class="vf-typewriter-scene">
<span class="vf-typewriter-line">
<span class="vf-typewriter-prompt">$</span> previous-command
</span>
<span class="vf-typewriter-text">text to animate here</span>
<span class="vf-typewriter-line">
<span class="vf-typewriter-prompt">$</span> next-command
</span>
</div>
</div>
Full HTML + CSS + JS, copy-paste ready — with hundreds of premium effects.
Customize
Options passed to the API or data-* attributes:
| Option / property | Default | Effect |
|---|---|---|
| animation-duration (vfType) | 4s | Duration of one full typing cycle. Increase to 6–8s for slow, readable typing; reduce to 2s for a snappy feel. |
| steps(20) in vfType | 20 | Number of columns revealed per cycle — should match the character count of your text for perfect alignment. Count your characters (including spaces) and adjust. |
| max-width on .vf-typewriter-text | 280px | Maximum visible length. Align with the actual text width at your chosen font size to avoid clipping. |
| color on .vf-typewriter-text | #10b981 | Text and cursor color (the border-right inherits the same value via the color property). |
| font-size on .vf-typewriter-text | 1.2rem | Animated text size. Adjust in sync with max-width and steps(). |
| font-variation-settings on .vf-typewriter-text | "MONO" 1, "CASL" 0, "wght" 400 | Recursive variable font axes. "CASL" 1 = cursive style, "wght" 700 = bold, "MONO" 1 required for fixed-width spacing. |
| color on .vf-typewriter-prompt | #8b5cf6 | Prompt symbol color ($). Adapt to your brand palette. |
| color on .vf-typewriter-line | rgba(255,255,255,0.3) | Opacity of context lines (static commands around the animated text). |
| gap on .vf-typewriter-scene | 12px | Vertical spacing between terminal lines. Increase to air out, decrease to compact. |
FAQ
@keyframes, an animation property, and font-variation-settings. No .js file needed. Copy the HTML and CSS, add the Recursive font via Google Fonts, and you're done.<span class="vf-typewriter-text"> directly. Then adjust steps(N) in the vfType animation to match your character count (include spaces), and tweak max-width so the line is not clipped.<span> elements with absolute positioning and offset their animation-delay values. With a small JS helper, the cleanest approach is to swap textContent at the reset moment (when width returns to 0).