Text Generate Effect — Free HTML CSS JS Reveal Snippet

Text Generate Effect · Animations · Plain HTML, CSS & JS · Live preview

Share & Support

What's included

Features

Word-by-word reveal
Each word is wrapped in its own animatable span.
Blur-in materialize
Words sharpen from blur for the AI look.
Staggered cascade
setTimeout offsets each word by 90ms.
Scroll-triggered
IntersectionObserver fires it once in view.
Gradient accent words
Listed words resolve into a color gradient.
Replayable
Timers clear and re-run on demand.
Wrap-preserving
inline-block words keep natural line breaks.
No per-frame JS
Transitions and the observer do the work.

About this UI Snippet

Text Generate Effect — Word-by-Word Blur-In Reveal

Screenshot of the Text Generate Effect snippet rendered live

The text-generate effect is the headline animation popularized by AI products: instead of appearing all at once, a sentence materializes word by word, each one un-blurring and rising into place on a gentle stagger, as if the page is "thinking" the text into existence. This snippet recreates it in plain HTML, CSS, and vanilla JavaScript, with scroll-triggered playback and gradient-highlighted accent words.

Splitting text into animatable words

The source sentence lives in a data-text attribute. On load, JavaScript splits it on spaces and wraps each word in a <span class="tg-word">, rejoining them with spaces so the natural line-wrapping is preserved. Wrapping each word individually is what lets them animate independently — you can't transition parts of a single text node, so the split into spans is the foundation of the whole effect.

The blur-in transition

Each word starts at opacity: 0, filter: blur(10px), and translateY(6px). Adding an .in class transitions all three to their resting values over half a second, so the word sharpens from a soft blur, fades up, and settles. The blur is the signature touch — it reads as "rendering" rather than a plain fade, which is exactly the generative-AI aesthetic. Each word uses display: inline-block so the transform applies (transforms are ignored on inline elements) and white-space: pre so spacing stays intact.

The stagger

The animation feels alive because words don't appear simultaneously. A loop schedules each word's .in class with setTimeout at 120 + i * 90 milliseconds, so word i starts 90ms after the one before it. That cascade is what makes the sentence appear to type or stream itself in. All timers are tracked in an array and cleared before each run so replays don't overlap or double-fire.

Scroll-triggered playback

A headline that animates before it's on screen is wasted, so an IntersectionObserver watches the element and only calls run() when at least 40% of it enters the viewport, then disconnect()s so it fires once. This is the standard, performant way to trigger scroll animations — no scroll listener, no per-frame math, and the browser handles the visibility detection.

Gradient accent words

Specific words listed in the ACCENT array get an extra class that, once revealed, paints them with a background-clip: text gradient so they stand out in color while the rest stay white. Because the gradient is applied only in the .in state, the accent words blur in like the others and then resolve into color, which keeps the emphasis from being visible before the animation reaches them.

Replayable

A replay button clears the timers, strips the .in classes, and re-runs the stagger, so you can demo the effect repeatedly. The same run() function powers both the initial scroll trigger and the replay.

Customizing it

Change the per-word delay to speed up or slow down the "generation," adjust the blur amount for a softer or sharper materialize, edit the ACCENT list to highlight different words, or swap the gradient colors. For a character-by-character variant, split on '' instead of ' '. Pair it with a sparkles text flourish or a shimmer button call to action beneath the headline.

Build with AI

Build, Understand, Optimize, and Extend It With AI

Ask an AI coding assistant like Claude to walk through why filter: blur(10px) transitioning to blur(0) reads as "generating" text while a plain opacity fade doesn't, and how the 120 + i * 90 millisecond formula in run() produces the stagger from a flat array of setTimeout calls. It's also worth asking about the tradeoffs — whether that many independent setTimeout calls could jank on very long sentences, and whether a single CSS animation-delay per word would be cheaper than JS-driven timers. For extending it, ask for per-word random blur amounts for a less mechanical feel, a version that streams words in as they'd arrive from a real streaming API response, or a variant that reveals by character instead of by word. 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 a scroll-triggered, word-by-word "text generate" reveal effect in plain HTML, CSS, and JavaScript — no animation library, no scroll listener.

Requirements:
- The full sentence must live in a data-text attribute on the heading element, not as visible markup, so JavaScript is the only thing that renders the words.
- On load, split the sentence on spaces and wrap every word in its own inline-block span, rejoining with literal spaces so natural line-wrapping is preserved; some specific words should be flaggable (via a separate list) to receive an "accent" class.
- Each word span must start at opacity 0, filter: blur(10px), and a small upward translateY offset, with a CSS transition on all three properties.
- Accent-flagged words must only reveal their gradient text color (via background-clip: text) once they reach the revealed state, so the gradient is invisible before the animation reaches that word.
- A run function must clear any previously scheduled timers, remove the revealed class from every word, and then re-schedule each word's reveal with an increasing setTimeout delay so the words un-blur and rise in left-to-right sequence rather than all at once.
- The whole animation must not start until the heading is at least 40% visible in the viewport, detected with an IntersectionObserver that disconnects itself after firing once.
- Add a replay button that re-runs the same reveal function on demand, reusing the identical timer-clearing logic so replays never overlap or double-fire.

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 headline waits until it scrolls into view.
  2. 2
    Scroll it into viewWords un-blur and rise in one after another on a stagger.
  3. 3
    Watch the accentsHighlighted words resolve into a gradient as they appear.
  4. 4
    Click ReplayThe sentence clears and regenerates word by word.
  5. 5
    Edit the textChange the data-text attribute to your own sentence.
  6. 6
    Tune the timingAdjust the per-word delay and blur amount.

Real-world uses

Common Use Cases

AI product headlines
Pair with a shimmer button CTA.
Landing hero copy
Reveal a tagline above a feature tabs showcase.
Section intros
Animate a lead-in before a testimonial wall.
Storytelling pages
Stream narrative atop stacking scroll cards.
Quote reveals
An alternative to a static gradient text headline.
Reveal-on-scroll demos
A reference for IntersectionObserver staggers.

Got questions?

Frequently Asked Questions

You can't transition parts of a single text node, so each word is wrapped in its own inline-block span. That lets every word carry its own opacity, blur, and transform and animate independently, which is what makes the staggered word-by-word reveal possible. Rejoining with spaces preserves natural line wrapping.

Each word starts at filter: blur(10px) and transitions to blur(0). The blur reads as the text rendering or focusing into existence rather than a plain fade, which is the signature of generative-AI interfaces. Combined with a slight upward translate and fade, it feels like the words are being thought into place.

An IntersectionObserver watches the heading and runs the animation when 40% of it enters the viewport, then disconnects so it fires once. This avoids animating off-screen, needs no scroll listener or per-frame math, and lets the browser handle visibility detection efficiently.

Words listed in the ACCENT array get an extra class whose gradient (via background-clip: text) only applies in the revealed .in state. So accent words blur in like the rest and then resolve into color exactly when they appear, rather than showing their highlight before the animation reaches them.

Split the text into word spans in render rather than innerHTML, and drive each word's in class from state toggled on a stagger (a setTimeout loop or a CSS transition-delay based on index). Trigger with an IntersectionObserver in a mount effect, clearing timers on cleanup. In Tailwind, use blur and opacity utilities with arbitrary transition-delay-[...] values per word index.