Text Reveal on Scroll — CSS & JavaScript Examples

Animate text into view as the user scrolls, line by line, word by word, or character by character. CSS and JavaScript approaches with copyable code.

Text Lines Reveal on Scroll

Text lines slide up into view from below as they enter the viewport. The outer element has overflow:hidden, which clips text below the baseline. The inner text starts at translateY(110%) and animates to translateY(0) using animation-timeline: view().

↓ Scroll down to see the text reveal

The quick brown fox jumps over the lazy dog. Scroll to reveal each line.
Build great scroll experiences with pure CSS.
No JavaScript required. CSS scroll-timeline does the work.
Copy the code and use it anywhere. Works on any element.
How the CSS line reveal works ↓
EarlyLate
Fast (narrow)Slow (wide)

Uses a named view-timeline on the section + overflow:hidden on the wrapper to create a clean line-reveal as the section scrolls into view.

Word-by-Word Text Reveal

Each word animates individually with a staggered animation-delay, creating a ripple effect across the line. Words use animation-timeline: view() with inline animation-delay applied via HTML attributes.

↓ Scroll down to see the word reveal

Design  beautiful  scroll  experiences.

Each  word  appears  in  sequence.

Pure  CSS,  no  library.

Copy  and  use  anywhere.

How the word-by-word reveal works ↓
EarlyLate
NoneMax

Split your text into <span> elements. Apply increasing animation-delay to each word span for the stagger effect.

Text Reveal with JS and Intersection Observer

A cross-browser approach: elements start hidden with opacity: 0; translateY(30px). The Intersection Observer API detects when each element enters the viewport and adds a .visible class that triggers the CSS transition. Works in all modern browsers (97%+ global support), no CSS scroll-timeline needed.

Intersection Observer

Fires when the element enters the viewport. Works in all modern browsers.

Universal Support

Chrome, Firefox, Safari, Edge; no CSS scroll-timeline required.

Configurable

Adjust threshold, rootMargin, and transition speed for fine-grained control.

How the JS text reveal works ↓
0.2s1.5s

The observer fires when 30% of the element is visible. Toggle the speed to see slow or fast reveals.

Text Reveal with fullPage.js

In a fullscreen layout, text reveals work best when tied to section transitions, not scroll position. fullPage.js fires the afterLoad callback the moment a section snaps into view, so you just toggle a CSS class. No IntersectionObserver, no animation-timeline browser issues. Works everywhere. Looks amazing.

Loading preview...

fullPage.js adds

  • Section-based callbacks
  • Cross-browser support
  • Scroll snapping
  • Touch & keyboard nav
  • No observer setup
  • 60fps performance
Get fullPage.js →

CSS Line-by-Line Text Reveal Animation

The line reveal is a pure CSS text reveal animation that uses two layers: an outer <span> with overflow: hidden that acts as a mask, and an inner <span> that starts positioned below the visible area. Because the parent clips overflow, the inner text is completely invisible until the animation begins:

HTML

<span style="overflow: hidden; display: block">
  <span class="reveal-line">This line slides into view</span>
</span>

CSS

.reveal-line {
  display: block;
  transform: translateY(110%);
  animation: slide-up both linear;
  animation-timeline: view();
  animation-range: entry 45% entry 75%;
}
@keyframes slide-up {
  to { transform: translateY(0); }
}

The animation is driven by animation-timeline: view(), a CSS Scroll Timeline property that links animation progress directly to scroll position instead of clock time. The animation-range: entry 45% entry 75% defines the scroll window: the reveal starts when 45% of the section has entered the viewport and completes at 75%.

The effect dropdown in the demo above swaps the @keyframes rule. "Slide Up" uses translateY(110%) → translateY(0); "Slide Down" reverses the direction; "Blur" adds filter: blur(6px) → blur(0) for a focus-pull effect; "Scale" grows from scale(0.4); and "Flip" rotates from rotateX(90deg) using the parent's perspective: 600px. All of these are pure CSS; no JavaScript involved.

Browser support: animation-timeline works in Chrome 115+, Edge 115+, and Safari 26+. Firefox does not support it yet. For cross-browser production use, wrap these styles in @supports (animation-timeline: view()) and provide a JavaScript fallback.

Word-by-Word Text Reveal Animation CSS

The word reveal splits text into individual <span> elements, each wrapped in an overflow: hidden container. Every word gets the same base animation, but with an incrementally increasing animation-delay to create a staggered cascade:

HTML

<!-- Each word gets a stagger index via --i -->
<span style="overflow:hidden">
  <span class="word" style="--i:0">Every</span>
</span>
<span style="overflow:hidden">
  <span class="word" style="--i:1">word</span>
</span>
<span style="overflow:hidden">
  <span class="word" style="--i:2">reveals</span>
</span>

CSS

.word {
  display: inline-block;
  transform: translateY(100%);
  animation: slide-up both linear;
  animation-timeline: view();
  animation-range: entry 40% entry 80%;
  animation-delay: calc(var(--i) * 5%);
}

The stagger of 5% per word with 6 words means the last word starts 30% after the first, tight enough to feel cohesive, wide enough to read as a sequence. Combined with animation-timeline: view(), the delay offsets each word's reveal within the scroll range.

The effect options work identically to the line reveal: "Slide Up + Blur" adds a defocus-to-focus transition; "Scale" grows each word from a small size; "Flip" rotates each word into place around the X axis. The stagger control in the demo above adjusts the delay multiplier in real time so you can find the right timing by scrolling through the preview.

This is one of the most searched-for text reveal animation CSS patterns. The pure CSS approach here means zero runtime JavaScript; the browser's compositor thread handles the entire animation, keeping the main thread free.

Text Reveal with JavaScript Intersection Observer

The Intersection Observer approach is the cross-browser alternative to CSS scroll-timeline. Each target element starts hidden and transitions in when a .visible class is added:

CSS

.reveal {
  opacity: 0;
  transform: translateY(30px);
  transition: opacity 0.6s ease, transform 0.6s ease;
}
.reveal.visible {
  opacity: 1;
  transform: translateY(0);
}

JavaScript

const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      entry.target.classList.add('visible');
      observer.unobserve(entry.target);
    }
  });
}, { threshold: 0.3 });

document.querySelectorAll('.reveal').forEach(el => observer.observe(el));

The key difference from the pure CSS approach is that Intersection Observer fires a one-shot trigger: it adds the class and calls unobserve(). The element animates once and stays visible. There is no native "scrubbing" (reversing on scroll back) unless you add logic to remove the class when the element leaves the viewport.

Configuration is minimal: threshold controls how much of the element must be visible before triggering (0.3 = 30%), and rootMargin can offset the detection zone (e.g., '-50px' to trigger slightly after the element enters). The transition speed is set entirely in CSS via the transition-duration property on the target elements; the JavaScript only toggles the class.

This works in every modern browser including Firefox, Safari, Chrome, and Edge. For stagger effects, apply increasing transition-delay values to sibling elements via CSS or inline styles, the same technique as the pure CSS version, but triggered by the observer class toggle instead of scroll-timeline.

CSS vs JavaScript Approach

Both approaches produce similar visual results. The key differences are browser support, performance characteristics, and flexibility.

CSS scroll-timeline JavaScript (IntersectionObserver)
Browser support Chrome, Edge, Safari 26+ only All modern browsers
Performance Compositor thread (no JS cost) Main thread (minimal JS cost)
Scrubbing (reverse on scroll back) Automatic Requires extra logic
Stagger delays animation-delay per span CSS animation-delay per span
Trigger control animation-range threshold + rootMargin
Complexity CSS only, no JS ~15 lines of JS

For production sites, use CSS with an @supports check and an IntersectionObserver fallback for Firefox users.

FAQ

How do I reveal text on scroll with CSS?
Wrap each text line in an overflow:hidden container. Inside, add an element starting at translateY(110%) that animates to translateY(0) using animation-timeline: view(). The overflow clip hides the text below the baseline until it rises into view.
How do I animate text word by word on scroll?
Split your text into individual word <span> elements. Apply increasing animation-delay inline styles (0ms, 60ms, 120ms…). Each span gets the same animation-timeline: view() linked to the parent section's position, but starts at a different time offset.
Does text reveal animation work in Firefox?
The CSS animation-timeline: view() approach does not work in Firefox by default. For full cross-browser support, use the Intersection Observer approach (Demo 3 above). You can also use @supports to serve CSS scroll-timeline to supported browsers while falling back to IntersectionObserver for Firefox.
How to add a stagger effect to scroll text reveal?
Add increasing animation-delay values as inline styles: style="animation-delay:0ms", style="animation-delay:60ms", etc. For dynamically generated content, use a script to set el.style.animationDelay = (index * 60) + 'ms' on each word or character span after splitting the text.
What is the overflow:hidden trick for text reveal?
The outer element clips its content. When the inner text is at translateY(110%) it sits below the clip boundary and is invisible. As it animates toward translateY(0) it enters the visible area from below, creating the reveal effect. Without overflow:hidden, you would see the text below its final position.

Make Your Website Stand Out with Fullscreen Effects

Add scroll transitions, parallax and animations to your site with fullPage.js. One component, 80+ effects.

Brandire
New World of Work
OW Consulting

Powering fullscreen design for Google, Sony, BBC, eBay & more

Get fullPage.js
+ Suggest Effect