You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Vanilla JS实现滚动时文本逐行显示的效果

滚动逐行显示文本实现方案

1. 原生JS实现行元素包裹span

针对你给出的带<br>硬换行的文本场景,实现代码如下:

// 选中所有需要处理的文本段落
const paragraphs = document.querySelectorAll('p');

paragraphs.forEach(p => {
  // 按<br>标签分割内容,过滤空行
  const lines = p.innerHTML.split(/<br\s*\/?>/i).filter(line => line.trim());
  // 拼接生成带span包裹的新内容
  p.innerHTML = lines.map(line => `<span class="line">${line.trim()}<br></span>`).join('');
});

执行后即可得到你期望的每行内容独立包裹span的结构。
如果是没有硬写<br>、由容器宽度自动换行的文本,可以用Range API实现行拆分,示例代码如下:

function wrapAutoLines(el) {
  const text = el.textContent;
  el.innerHTML = '';
  const words = text.split(' ');
  let currentLine = '';
  // 临时元素用于计算行宽
  const testSpan = document.createElement('span');
  testSpan.style.visibility = 'hidden';
  el.appendChild(testSpan);
  
  words.forEach(word => {
    const testContent = currentLine + word + ' ';
    testSpan.textContent = testContent;
    // 行宽超出容器时拆分新行
    if (testSpan.offsetWidth > el.offsetWidth && currentLine) {
      const lineSpan = document.createElement('span');
      lineSpan.className = 'line';
      lineSpan.textContent = currentLine;
      el.appendChild(lineSpan);
      currentLine = word + ' ';
    } else {
      currentLine = testContent;
    }
  });
  // 插入最后一行
  const lastLine = document.createElement('span');
  lastLine.className = 'line';
  lastLine.textContent = currentLine;
  el.appendChild(lastLine);
  el.removeChild(testSpan);
}

2. 滚动触发逐行显示效果

采用性能更优的IntersectionObserver实现,无需监听滚动事件,代码如下:

样式代码

.line {
  /* 初始隐藏状态 */
  opacity: 0;
  transform: translateY(15px);
  /* 过渡动画配置 */
  transition: all 0.5s cubic-bezier(0.22, 1, 0.36, 1);
  /* 自动换行场景需要开启block属性 */
  display: block;
  margin-bottom: 0.2em;
}
.line.show {
  opacity: 1;
  transform: translateY(0);
}

逻辑代码

// 创建元素观察者
const lineObserver = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    // 行元素进入视口时触发显示
    if (entry.isIntersecting) {
      entry.target.classList.add('show');
      // 已显示的元素取消监听减少性能消耗
      lineObserver.unobserve(entry.target);
    }
  });
}, {
  // 元素露出10%时触发动画
  threshold: 0.1,
  // 可调整rootMargin实现提前触发效果
  rootMargin: '0px 0px -50px 0px'
});

// 给所有行元素绑定监听,如需依次延迟显示可加递增的transition-delay
document.querySelectorAll('.line').forEach((line, index) => {
  // 每一行延迟0.1s依次显示,不需要可以删掉下一行
  line.style.transitionDelay = `${index * 0.1}s`;
  lineObserver.observe(line);
});

内容的提问来源于stack exchange,提问作者Gg Wp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 10:06:03