Source Code

<div class="tf-wrap">
  <div class="tf-bubble">
    <span class="tf-text" id="tfText"></span><span class="tf-cursor"></span>
  </div>
</div>

AI Token Flicker Typing Loader — Streaming Token Guess Animation CSS JS

AI Token Flicker Typing Loader · Loaders · Plain HTML, CSS & JS · Live preview

What's included

Features

Dim candidate-word flicker settles into each real word in full color
Two-span architecture keeps settled text untouched while only the live word updates
Randomized flicker count and per-word pause for a natural, non-mechanical rhythm
Blinking cursor follows the live generation edge
Visually distinct from a three-dot bounce or a plain character typewriter
Mimics the metaphor of token-by-token autoregressive generation
Data-driven FINAL sentence and CANDIDATE_POOL array
Zero dependencies — vanilla DOM text manipulation only
Easy to wire into a real streaming API response
Compact chat-bubble layout, ready to drop into a thread

About this UI Snippet

AI Token Flicker Typing Loader — A Typing Indicator That Mimics Token-by-Token Generation

Screenshot of the AI Token Flicker Typing Loader snippet rendered live

The three-dot bounce is the default typing indicator everywhere, but it communicates nothing about what's actually happening when an AI model generates text token by token. This snippet takes a different approach inspired by that literal generation process: before each real word appears, a handful of dim, rapidly-flickering "candidate" words flash in place, then the actual word settles into full color — visually suggesting the model considering several possible next tokens before committing to one.

Two coexisting spans, not a full re-render

The revealed text lives in .tf-settled, appended to permanently word by word as each one finishes. The currently-flickering word lives in a separate .tf-guessing span appended right after it. Only the guessing span's textContent is replaced on every flicker tick — the settled text is never touched once written, so there's no flash of the whole paragraph re-rendering, only the live edge of generation visibly working.

Randomized flicker count and speed

Each word gets a randomized 3 to 5 "candidate" flickers pulled from a small pool of plausible filler words, each shown for about 55ms before the next candidate replaces it — fast enough to read as machine-speed consideration rather than a deliberate slow reveal. The number of flickers varies per word so the rhythm doesn't feel mechanically identical across the whole sentence.

A real word-by-word reveal loop

typeWord(index) recursively calls itself for the next word only after the current word's flicker sequence completes and is appended to the settled text, with a small randomized pause between words (90ms to roughly 210ms) so pacing feels closer to natural speech cadence than a fixed-interval typewriter.

Distinct from a three-dot bounce or a plain typewriter

A three-dot bounce says only "something is happening." A plain character-by-character typewriter (like the typewriter status log loader) says "text is being revealed" but implies the text is already fully known and just being played back. This flicker pattern specifically suggests uncertainty resolving into a decision per word — a much closer visual metaphor for autoregressive token generation, and a genuinely different read for users familiar with how AI text streaming actually looks and feels.

Customizing it

Replace FINAL with your own real generated sentence, or better, drive typeWord from an actual streaming API response: as each real token/word arrives from your backend, run a short flicker using recent-but-wrong candidate words (or simply the previous partial token) before settling on the true one. Adjust CANDIDATE_POOL, flicker count range, and timing to taste. Pair it with an AI thinking loader for the state before generation begins, switching to this component once the first real token streams in.

Build with AI

Build, Understand, Optimize, and Extend It With AI

Rather than assuming this is a typewriter effect with extra styling, paste this snippet's HTML, CSS, and JS into an AI coding assistant like Claude and ask it to explain exactly how the two-span structure (a permanent .tf-settled span versus a replaced-on-every-tick .tf-guessing span) avoids re-rendering the whole sentence on each flicker, and why that separation matters for performance as the sentence grows long. The same assistant can help optimize it \u2014 for instance asking whether the nested setInterval-inside-setTimeout recursion in typeWord could be restructured to avoid creating a new interval per word. It's also useful for extending it: ask it to drive the candidate flickers from a real model API's logprobs/alternative-token data instead of a random filler pool, add a subtle scale-in for the settling word, or support streaming multiple sentences with paragraph breaks. Treat the code less like a finished artifact and more like a starting point for a conversation.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build an AI chat "typing" indicator in plain HTML, CSS, and JavaScript \u2014 no libraries \u2014 that visually mimics token-by-token text generation instead of using a generic three-dot bounce.

Requirements:
- A chat bubble containing a growing sentence of already-revealed text plus a blinking cursor at the live edge.
- Reveal the target sentence one word at a time, but before each real word is committed, rapidly flicker through several dim, differently-colored "candidate" words in that same position (pulled from a small pool of plausible filler words) at a fast fixed interval, simulating the model considering multiple possible next tokens.
- After the flicker sequence for a word finishes, the real word must be appended in full color to a permanently-growing "settled" portion of the sentence that is never re-rendered on subsequent ticks \u2014 use two separate text-containing elements (one for settled text, one for the currently-flickering candidate) so unrelated DOM isn't rewritten every tick.
- Randomize both the number of candidate flickers per word (a small range, like 3 to 5) and the short pause between finishing one word and starting the next, so the pacing doesn't feel mechanically identical across the sentence.
- Keep a blinking block or bar cursor animated via CSS immediately after the live edge of the text at all times.
- Make the target sentence and the candidate word pool easy to swap out, since a real implementation would drive this from an actual token stream rather than a fixed string.

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

Step by step

How to Use

  1. 1
    Paste HTML, CSS, and JSA chat bubble appears with a blinking cursor, then word-by-word generation begins.
  2. 2
    Watch the flicker per wordSeveral dim candidate words flash rapidly before each real word settles in full color.
  3. 3
    Watch the sentence buildSettled words remain fixed while only the live edge keeps flickering.
  4. 4
    Reach the endThe cursor keeps blinking after the final word, ready for a real response to follow.
  5. 5
    Edit FINAL and CANDIDATE_POOLChange the target sentence and the pool of filler words used for flickers.
  6. 6
    Wire up real streamingCall typeWord-style logic from your actual token stream instead of the fixed FINAL string.

Real-world uses

Common Use Cases

AI chat response generation
Show this as the assistant\u2019s message streams in, pairing with an ai thinking loader for the state before generation starts.
Autocomplete and code-completion UIs
Suggest multiple candidate completions flickering before one is chosen or accepted.
AI writing assistants
A more literal visualization of text generation than a generic loading spinner.
Teaching token-generation metaphors in UI
A reference for communicating a specific technical process through animation.
Search-with-AI and summarization tools
Differentiate AI-generated content from static loading elsewhere on the page.
Related: Typing Indicator
See the Typing Indicator for the classic three-dot alternative to this pattern.
Related: Realistic Network Progress Bar
See the Realistic Network Progress Bar for a related loaders pattern worth pairing with this one.

Got questions?

Frequently Asked Questions

A three-dot bounce communicates only that something is happening, with no relation to the actual content. This component flickers plausible candidate words in a dim tone before each real word settles in full color, directly visualizing the idea of a model considering multiple possible next tokens before committing \u2014 a much more literal metaphor for how AI text generation actually works.

The revealed sentence lives in a separate .tf-settled span that is only ever appended to, never rewritten. The currently-flickering word lives in its own .tf-guessing span whose textContent is replaced on each tick. Keeping them separate means only the live edge of generation re-renders, not the whole growing paragraph.

Instead of iterating the fixed FINAL string, call your flicker-then-settle logic each time a real token or word arrives from your SSE/WebSocket stream: run a short flicker of a few candidate strings (or the model\u2019s own top alternative tokens, if your API exposes them), then append the real received word to the settled span exactly as typeWord does.

Each word draws a random 3 to 5 candidates from the pool, shown at a fixed fast interval, so the total flicker duration naturally varies word to word. This avoids the identical, robotic rhythm a fixed-count fixed-speed loop would produce across an entire sentence.

Yes \u2014 if your model API exposes alternative token candidates and their probabilities (some do via logprobs), swap CANDIDATE_POOL\u2019s random pick for those real alternatives so the flicker genuinely reflects the model\u2019s own uncertainty rather than decorative filler words.

Yes. Keep settledText and the current guessWord in state, run the flicker sequence inside an effect keyed to the current word index (using setInterval with cleanup), and append to settledText only once the flicker sequence completes \u2014 render both pieces of state as adjacent spans exactly as the vanilla version does.