如何实现标题进入视口时才触发逐字动画?
实现标题进入视口时触发逐字动画的解决方案
问题原因
你的代码核心问题是默认给所有.heading-reveal span绑定了动画属性,页面加载时动画已自动启动,这就是所有标题动画同时触发的根本原因——和Intersection Observer的threshold参数无关,是CSS初始样式逻辑错误导致的。
修复方案
将动画相关样式移到单独的类中,仅当标题进入视口时才为元素添加该类,确保动画只在元素可见时触发。
修改后的代码
JavaScript
window.addEventListener('DOMContentLoaded', function() { const observerOptions = { root: null, rootMargin: "0px", threshold: 0.1 // 可按需调整,比如设为0.5表示元素50%进入视口时触发 } const observer = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.querySelectorAll('span').forEach((span, index) => { span.style.setProperty('--word-index', index); span.classList.add('reveal'); }); observer.unobserve(entry.target); // 确保每个标题只触发一次动画 } }); }, observerOptions); document.querySelectorAll('.heading-reveal').forEach(target => { observer.observe(target); }); });
CSS
.heading-reveal { display: flex; flex-wrap: wrap; } .heading-reveal span { opacity: 0; } .heading-reveal span.reveal { animation: revealWord 0.5s forwards; animation-delay: calc(var(--word-index) * 0.25s); } @keyframes revealWord { to { opacity: 1; } }
HTML
<h1 class="heading-reveal"> <span>Title</span> <span>Goes</span> <span>Here</span> </h1> <h1 class="heading-reveal"> <span>2nd</span> <span>Title</span> <span>Here</span> </h1> <h1 class="heading-reveal"> <span>3rd</span> <span>Title</span> <span>Here</span> </h1>
关键调整说明
- CSS样式拆分:将动画属性从默认
span选择器移到.reveal类中,默认状态下span仅保持opacity:0,无动画效果。 - 触发时机控制:只有当Intersection Observer检测到标题进入视口时,才为每个span添加
reveal类并设置--word-index变量,启动逐字动画。 - DOM加载优化:将
window.onload替换为DOMContentLoaded,更早开始监听元素,避免不必要的延迟。
内容的提问来源于stack exchange,提问作者Dascaliu Vlad
相关产品推荐
相关产品推荐

