
This is a lightweight approach for revealing text content word by word with a subtle fade-and-slide-in effect.
It wraps each word in a <span>, then uses CSS animations with staggered delays to make them appear sequentially.
Features:
- Precise word splitting – Handles punctuation and whitespace correctly
- Dynamic timing – Each word animates with progressive delay
- CSS-controlled effects – Customize transitions via keyframes
- Responsive by default – Works at any viewport size
- Simple implementation – Works with just a few lines of JavaScript and CSS
See It In Action:
How to use it:
1. Wrap the target text in an element with the word-reveal class:
<p class="word-reveal"> Your Text Here </p>
2. Define the keyframe animation and styling for the word reveal effect:
.word-reveal > span {
display: inline-block; /* Allows transforms and keeps flow */
opacity: 0;
transform: translateY(50px);
/* Reference the keyframes, set duration, easing, and fill mode */
animation: revealWord 0.8s ease-out forwards;
/* Adds space between words; adjust as needed */
margin-right: 0.3em;
}
@keyframes revealWord {
from {
opacity: 0;
transform: translateY(50px);
}
to {
opacity: 1;
transform: translateY(0);
}
}3. Use JavaScript to wrap each word in a <span> element and apply staggered animations:
function wrapTextNodes(element) {
// Use a more robust word splitting regex that handles punctuation
const words = element.textContent.match(/\b\w+\b|\S+/g) || [];
element.textContent = ""; // Clear existing text
words.forEach((word, index) => {
const span = document.createElement("span");
span.textContent = word + (index < words.length - 1 ? " " : "");
// Dynamic delay calculation
span.style.animationDelay = `${0.1 * (index + 1)}s`;
element.appendChild(span);
});
}
// Apply to all elements with word-reveal class
document.querySelectorAll(".word-reveal").forEach(wrapTextNodes);4. You can adjust the animation by modifying the CSS. Here are a few common customizations:
/* Change animation duration */
.word-reveal > span {
animation-duration: 0.5s; /* Faster animation */
}
/* Change animation timing function */
.word-reveal > span {
animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275); /* Bouncy effect */
}
/* Change animation distance */
@keyframes revealWord {
from {
transform: translateY(20px); /* Shorter distance */
}
to {
transform: translateY(0);
}
}FAQs:
Q: How can I control which elements get animated?
A: Simply add the `word-reveal` class to any element containing text you want to animate. You can target specific elements by using a different class name and updating the JavaScript selector.
Q: Will this affect SEO?
A: No. Since the text is still present in the DOM and only wrapped in spans, search engines can still read and index the content normally.
Q: How can I trigger the animation only when the element is visible?
A: Use the IntersectionObserver API. You’d observe the .word-reveal element. When it becomes intersecting (visible), you would then call wrapTextNodes() on it. You might also add a class (e.g., .is-visible) that triggers the animation, rather than applying it by default, to prevent it running before visibility. This avoids the performance hit of preparing off-screen elements.







