Typewriter Glitch
Character-by-character typewriter with random glitch bursts — character swaps and flickers that self-correct on each keystroke, looping endlessly.
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 from the data-text attribute is typed character by character via chained setTimeout calls (80–180 ms random delay per keystroke). A blinking cursor (|) is managed independently by a setInterval at 530 ms that appends or removes the | from the element's textContent — both timers coexist without blocking each other.
On each keystroke, a 25% probability triggers a glitch burst: 3 to 6 frames spaced 50 ms apart scan the already-typed characters and randomly replace 35% of them with a symbol from the set !@#$%^&*()_+-=[]{}|;:<>?/~`0123456789. During the burst, the element's opacity flickers between 1 and 0.6 to simulate a video-signal flicker. At the end of the burst, the correct text is restored before advancing to the next letter.
Once the full text is typed, the animation pauses for 2,000 ms then restarts from index 0 — infinite loop. The whole thing is a vanilla IIFE: zero dependencies, zero canvas, zero CSS animations. Courier New is a system font — no network request needed.
Accessibility
- No prefers-reduced-motion support in the shipped code: the animation runs regardless of OS setting. For motion-sensitive users, manually add
if (matchMedia('(prefers-reduced-motion: reduce)').matches) return;at the top of the IIFE. - The element exposes its content via
textContent— readable by screen readers, but rapid mutations during glitch bursts may trigger spurious announcements. Wrap in a<span aria-live="off">to suppress them. - High contrast: white text (
#fff) on a dark background (#0a0a0f) — ratio ≈ 21:1, WCAG AAA. - No keyboard interaction or focusable area: purely decorative effect. If used as a main heading, add an
aria-labelwith the final static text. - The
Courier Newfont is a ubiquitous system font — no FOUT, no network request.
Browser compatibility
Uses only textContent, setInterval, and setTimeout — no Canvas, no CSS animations, no recent APIs required.
Without JavaScript, the element shows the initial <code>|</code> character (static DOM content) — the page stays readable, no fatal error.
The code
HTML structure to paste into your page (CSS + JS available with a premium account):
<div class="kt-text kt-typewriter-glitch" id="typewriter1" data-text="YOUR TEXT_">|</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 |
|---|---|---|
| data-text | "TYPEWRITER_" | Text to type — edit this HTML attribute to change the content without touching the JS. |
| var fullText (JS) | "TYPEWRITER_" | JS fallback when data-text is absent. Set this variable directly in the code. |
| setTimeout(80 + Math.random() * 100) (JS) | 80–180 ms/char | Typing speed. Replace with setTimeout(typeNext, 120) for a constant pace, or drop to 40 ms for a fast-render feel. |
| Math.random() < 0.25 (JS) | 25% | Per-keystroke glitch burst trigger probability. Raise to 0.50 for a chaotic effect, lower to 0.05 for a nearly clean render. |
| Math.random() < 0.35 (JS) | 35% | Character corruption rate during a burst. 0.10 = subtle glitch, 0.70 = nearly unreadable text. |
| setInterval(530) (JS) | 530 ms | Cursor blink speed. 300 ms = fast, 800 ms = slow. Change the value inside setInterval. |
| .kt-text font-size (CSS) | 2.2rem | Text size. Increase to 4–6rem for full-screen hero usage. |
| .kt-typewriter-glitch font-family (CSS) | "Courier New", monospace | Font face. Swap to Georgia, Arial, or a locally-loaded font to change the aesthetic. |
| setTimeout(…, 2000) (JS — loop) | 2,000 ms | Pause before restarting after the full text is typed. Increase to 5,000 ms for a long hold, or remove the call to stop after one pass. |
FAQ
getElementById. To support multiple instances, extract the logic into a parameterized function: function initTypewriter(id, text) { var el = document.getElementById(id); var fullText = text; … typeNext(); } then call it once per element with its id and text.setTimeout(function() { idx = 0; typeNext(); }, 2000) in the final branch of typeNext() — the animation then stops on the blinking cursor once the full text is displayed.setInterval and replace border-right: 3px solid rgba(255,255,255,.7) with border-right: none in .kt-typewriter-glitch. In typeNext(), also remove the (cursorVisible ? '|' : '') concatenations.