Text✨ Premium

Typewriter Delete

A recursive setTimeout types and deletes words in a loop — CSS blinking cursor, independent typing and deletion speeds, infinite cycle.

JSTypewriterLoop

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

Landing hero — Rotating tagline with strong identity — Typewriter Delete example 1

① Landing hero — Rotating tagline with strong identity

WhenThe homepage showcases several value pillars (create, design, build…) and you want to cycle through them without cluttering the screen with a static list.
WhyThe effect focuses attention on one word at a time, improves readability, and creates dynamism without distracting from the main CTA below.
SettingsWords: ['CREATE', 'DESIGN', 'BUILD', 'INSPIRE']; font-size 3rem; typing delay 120 ms, word pause 2 000 ms; color = brand primary hue.
Search bar — Animated query suggestions — Typewriter Delete example 2

② Search bar — Animated query suggestions

WhenAn internal search engine or doc bar displays popular query examples to guide the user when the field is empty.
WhyThe blinking text mimics real typing, naturally draws the eye to the bar, and reduces the 'I don't know what to search' friction.
SettingsWords: ['React hooks', 'CSS Grid', 'Tailwind v4', 'TypeScript']; font-size 1rem; color #a5b4fc; typing delay 80 ms, deletion 40 ms, pause 2 000 ms.
Command terminal — Rotating developer CLI — Typewriter Delete example 3

③ Command terminal — Rotating developer CLI

WhenA CLI landing page, doc page, or interactive README wants to show the tool's key commands to give a quick sense of usage.
WhyThe monospace aesthetic + blinking cursor reinforces the terminal identity — commands that type and erase themselves make users want to try them.
SettingsWords: ['npm install mylib', 'git commit -m feat', 'yarn build', 'npx deploy --prod']; color #4ade80 (terminal green); typing delay 60 ms, deletion 30 ms.

How it works

The animation relies on a recursive setTimeout — no requestAnimationFrame. On each tick, a single textContent property on the <span> is updated with a substring(0, n) of the current word: n increments on typing, decrements on deletion. Two delays coexist: 100 ms per character added, 50 ms per character removed (2× faster).

The blinking cursor is entirely CSS: a border-right: 3px solid #22d3ee set on the <span> itself, animated by @keyframes blinkCursor which toggles border-color: transparent at 50% with a step-end timing function — the blink is an instant switch, not a gradual fade.

When charIndex reaches the word length, a 1 500 ms pause elapses before deletion starts (isDeleting = true). When the index drops back to 0, a 300 ms pause precedes the next word — obtained via typewriterIndex = (typewriterIndex + 1) % typewriterWords.length. The array loops infinitely.

The replayTypewriterDelete() function clears textContent, resets all counters, and restarts the cycle from the first word — intended to be wired to a button or a business event. It must be exposed on window when called from an inline onclick attribute (outside the IIFE).

Accessibility

  • No prefers-reduced-motion support: neither the CSS nor the JS checks this preference — the cursor blinks and words cycle indefinitely even if the OS signals reduced motion. Add this check manually if your audience is sensitive to motion.
  • Color contrast: #22d3ee text on #0a0a0f background achieves a ratio > 8:1 — well above the WCAG AA threshold (4.5:1).
  • Text is real DOM textContent, not an image: screen readers read the displayed words, but the absence of aria-live or role="status" means content changes are not announced automatically.
  • The Replay button is a native <button> — keyboard-focusable (Tab + Enter), in the normal tab order.
  • The CSS cursor (border-right blinking) is purely decorative and requires no text or aria equivalent.

Browser compatibility

Uses setTimeout, textContent, and CSS animations — available in all browsers for over 10 years. Zero external dependencies.

Chrome 88+✓ Full
Firefox 87+✓ Full
Safari 15+✓ Full
Edge 88+✓ Full
Mobile iOS✓ Full
Android Chrome✓ Full

If JavaScript is disabled, the <code>&lt;span&gt;</code> stays empty — no fatal error, the page stays functional. The CSS cursor blinks on its own.

The code

HTML structure to paste into your page (CSS + JS available with a premium account):

index.html — structure
<div class="demo-preview">
  <span class="demo-text text-typewriter-delete" id="typewriterDeleteText"></span>
  <!-- Replay button calls replayTypewriterDelete() — expose it on window if needed -->
  <button class="replay-btn" onclick="replayTypewriterDelete()">Replay</button>
</div>
🔒 Unlock the full code — from €2.99 the first month

Full HTML + CSS + JS, copy-paste ready — with hundreds of premium effects.

Customize

Options passed to the API or data-* attributes:

Option / propertyDefaultEffect
typewriterWords (JS, line 3) ['CREATE', 'DESIGN', 'BUILD', 'INSPIRE'] Array of words to cycle through — replace with your own strings. Unlimited length, scrolling is modular.
.text-typewriter-delete { color } #22d3ee Text AND cursor color in one change — border-color inherits from color if not overridden separately.
.text-typewriter-delete { border-right-width } 3px Cursor thickness. 2px for a thin cursor, 4–5px for a thick terminal-style cursor.
delay = 100 (typing, JS) 100 ms Delay between each character added. 60–80 ms = fast typing, 150–200 ms = human-like pace with hesitations.
delay = 50 (deletion, JS) 50 ms Delay between each character removed. Deletion is 2× faster than typing by default — adjust the ratio to taste.
delay = 1500 (post-word pause, JS) 1 500 ms How long the complete word is shown before deletion begins. 800 ms = lively pace, 2 500 ms = comfortable reading.
delay = 300 (between-word pause, JS) 300 ms Wait between end of deletion and start of next word. 0–100 ms gives a mechanical feel, 500 ms a more relaxed rhythm.
.demo-text { font-size } 2.5rem Text size. The effect works from 0.9rem (input placeholder) to 5rem (full-screen hero) with no JS changes.

FAQ

Yes — the code does not check prefers-reduced-motion. To respect this preference, add at the top of the start function: if (window.matchMedia('(prefers-reduced-motion:reduce)').matches) return; — the effect will not start on affected systems.
Expose the function globally by adding window.replayTypewriterDelete = replayTypewriterDelete; inside the IIFE (before closing), then call window.replayTypewriterDelete() from any event — section reload, end of video, scroll trigger, etc.
Not directly — the code targets a single id="typewriterDeleteText". For multiple instances, refactor the logic into a factory function: function makeTypewriter(el, words, opts) { … } with its own local state (index, charIndex, isDeleting, timer), and call it on each target element.