Scroll-Triggered Text Reveal Animation

Text animations that reveal on scroll with word-by-word and character-by-character fade-in, slide-up, and blur-to-focus effects. Uses Intersection Observer for performance, with configurable stagger delays.


Scroll-Triggered Text Reveal Animation


Create modern, performant scroll-triggered text reveal animations with word-by-word or character-by-character effects. This snippet includes fade-in, slide-up, blur-to-focus transitions, stagger delays, and an Intersection Observer implementation so animations run only when elements enter the viewport.

HTML Structure

Wrap any text in containers with data attributes for the reveal mode. Use data-reveal="word" for word-by-word, data-reveal="char" for character-by-character, or data-reveal="blur" for blur-to-focus blocks.

<section class="reveal-section" data-reveal="word">
  <h2>Your headline splits into words</h2>
</section>

<section class="reveal-section" data-reveal="char">
  <p>Character by character.</p>
</section>

<section class="reveal-section" data-reveal="blur">
  <p>This block fades in with blur-to-focus.</p>
</section>

Intersection Observer

The script observes each .reveal-section and adds the class is-visible when the section enters the viewport (with optional root margin and threshold). No scroll listeners—efficient and battery-friendly.

const observer = new IntersectionObserver(
  (entries) => {
    entries.forEach((entry) => {
      if (entry.isIntersecting) {
        entry.target.classList.add("is-visible");
      }
    });
  },
  { rootMargin: "0px 0px -80px 0px", threshold: 0.1 }
);

document.querySelectorAll(".reveal-section").forEach((el) => observer.observe(el));

CSS: Word-by-word and character stagger

Words and characters are wrapped in spans (via JS). Each gets a --delay custom property for staggered animation. Transitions use transform, opacity, and filter for smooth fade-in and slide-up.

.reveal-word span {
  transform: translateY(110%);
  transition: transform 0.8s cubic-bezier(0.16, 1, 0.3, 1);
  transition-delay: calc(var(--i, 0) * 0.06s);
}

.is-visible .reveal-word span {
  transform: translateY(0);
}

.reveal-blur {
  opacity: 0;
  filter: blur(10px);
  transform: translateY(20px);
  transition: opacity 0.8s ease, filter 0.8s ease, transform 0.8s ease;
}

.is-visible .reveal-blur {
  opacity: 1;
  filter: blur(0);
  transform: translateY(0);
}

Stagger delays

Stagger is applied by setting --i on each word or character span (0, 1, 2, …). Use transition-delay: calc(var(--i, 0) * 0.06s) for words and a smaller multiplier for characters (e.g. 0.03s) so the sequence feels natural.

You can reuse this pattern for headings, paragraphs, or full blocks—and combine word, character, and blur reveals on the same page for a modern, sleek feel.