☰
原生 JS 实现垂直无缝滚动跑马灯
2026/9/29 10:24:52 网站建设 项目流程

前言

在后台管理系统、H5 活动页面、网站首页经常会看到垂直公告跑马灯,多条消息自动向上滚动,实现公告、中奖名单、消息通知轮播。

网上很多简易跑马灯重置的时候会闪烁,本文采用transform + transition实现平滑动画,利用双层 setTimeout 解决无缝循环闪烁问题,同时增加暂停标记,可扩展鼠标移入暂停、移出继续播放,纯原生 JS,不依赖 jQuery。

实现特点:垂直向上滚动、动画平滑、无缝循环不闪烁、支持暂停控制,单条高度可配置。

完整源码

<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>原生JS垂直无缝跑马灯</title> <style> .marquee_box { width: 320px; height: 38px; /* 可视区域高度 = 单条高度,只展示一条 */ overflow: hidden; border: 1px solid #eee; border-radius: 4px; } .marquee_wrap { transition: transform 0.5s ease; } .marquee_item { height: 38px; line-height: 38px; font-size: 14px; padding: 0 10px; white-space: nowrap; } </style> </head> <body> <!-- 跑马灯DOM结构:外层可视盒子,内层滚动容器 --> <div id="marquee_box" class="marquee_box"> <div id="marquee_wrap" class="marquee_wrap"> <div class="marquee_item">恭喜用户001获得一等奖</div> <div class="marquee_item">恭喜用户002获得二等奖</div> <div class="marquee_item">恭喜用户003获得参与奖</div> <div class="marquee_item">恭喜用户004获得优惠券</div> </div> </div> <script> // 跑马灯相关js const marquee_box = document.getElementById('marquee_box'); // 可视盒子 const marquee_wrap = document.getElementById('marquee_wrap'); // 滚动容器 const marquee_itemHeight = 38; // 单条高度 let marquee_index = 0; // 当前滚动到第几条(偏移量倍数) let marquee_timer = null; // 定时器id let marquee_isPause = false; // 是否暂停标记 // 切换函数 function changeNotice() { if (marquee_isPause) { return; } marquee_index++; marquee_wrap.style.transform = `translateY(-${marquee_index * marquee_itemHeight}px)`; // 当滚动完所有条目,重置索引,无缝循环 if (marquee_index >= marquee_wrap.children.length) { // 等过渡动画结束后重置位置,不产生闪烁 setTimeout(() => { marquee_index = 0; marquee_wrap.style.transition = 'none'; marquee_wrap.style.transform = `translateY(0)`; // 恢复过渡动画 setTimeout(() => { marquee_wrap.style.transition = 'transform 0.5s ease'; }, 20) }, 400) } } // 5秒切换跑马灯 function startMarquee() { marquee_timer = setInterval(changeNotice, 5000); } // 启动跑马灯 startMarquee(); // 【可选扩展】鼠标移入暂停,鼠标移出继续 marquee_box.addEventListener('mouseenter', function () { marquee_isPause = true; }) marquee_box.addEventListener('mouseleave', function () { marquee_isPause = false; }) // 页面销毁清除定时器,防止内存泄漏 window.addEventListener('beforeunload', () => { clearInterval(marquee_timer); }) </script> </body> </html>

DOM 与 CSS 说明

<div id="marquee_box"> <!-- 可视容器,overflow:hidden 裁切超出内容 --> <div id="marquee_wrap"> <!-- 滚动容器,通过transform做位移 --> <div class="marquee_item">条目1</div> <div class="marquee_item">条目2</div> </div> </div>
  • marquee_box:可视盒子,固定高度,overflow:hidden,只显示一条公告
  • marquee_wrap:滚动容器,使用transform: translateY()垂直位移,配合transition实现平滑滚动动画
  • marquee_item:单条公告,高度固定,代码中marquee_itemHeight要和 css 高度保持一致

核心代码逐行解析

变量说明

表格

变量作用
marquee_box外层可视盒子
marquee_wrap滚动内容容器
marquee_itemHeight单条条目高度,位移计算基准
marquee_index当前滚动索引,记录当前是第几条
marquee_timer定时器 ID,用于清除轮播
marquee_isPause暂停标记,控制是否继续滚动

changeNotice () 滚动核心函数

function changeNotice() { // 如果标记为暂停,直接return,不执行滚动 if (marquee_isPause) { return; } marquee_index++; // 向上偏移,索引 * 单条高度 marquee_wrap.style.transform = `translateY(-${marquee_index * marquee_itemHeight}px)`; // 判断:滚动到最后一条了,准备重置 if (marquee_index >= marquee_wrap.children.length) { setTimeout(() => { marquee_index = 0; marquee_wrap.style.transition = 'none'; // 关闭动画,瞬间归位,不会出现反向回退动画 marquee_wrap.style.transform = `translateY(0)`; setTimeout(() => { marquee_wrap.style.transition = 'transform 0.5s ease'; // 重新开启动画 }, 20) }, 400) // 400ms 和动画时长保持一致,等滚动动画完全结束再重置 } }

重点解决闪烁原理: 当滚动到最后一条,先等待动画播放完毕,再关闭 transition,瞬间把容器位置归位到 0; 短暂延迟后,再重新开启 transition,下一次滚动继续有动画。 如果不关闭 transition 直接归位,会看到内容回弹向下滚动,出现明显闪烁。

startMarquee () 启动轮播

function startMarquee() { marquee_timer = setInterval(changeNotice, 5000); }

每隔 5s 执行一次滚动函数,可自行修改时间,比如 3000 代表 3 秒切换。

扩展:鼠标悬停暂停

marquee_box.addEventListener('mouseenter', function () { marquee_isPause = true; }) marquee_box.addEventListener('mouseleave', function () { marquee_isPause = false; })

鼠标移入公告区域暂停滚动,鼠标离开继续,后台系统公告常用交互。

其他拓展方向

  1. 横向跑马灯:把translateY改成translateX,高度改为宽度。
  2. 增加上下手动点击翻页按钮。
  3. 文字超出单行省略:css 增加text-overflow:ellipsis。
  4. 多条同时展示:修改 marquee_box 可视高度为 N*marquee_itemHeight。

知识点总结

  1. transform位移相比 top/left,开启 GPU 加速,性能更好,动画流畅
  2. transition控制过渡动画,重置位置时临时关闭动画,解决无缝轮播闪烁
  3. setInterval做定时轮播,使用标记变量控制暂停,不销毁定时器,适合频繁 hover 暂停场景
  4. 定时器用完要清除,防止内存泄漏
  5. 固定高度垂直跑马灯,单条高度 JS 和 CSS 必须统一

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询