应弃用marquee标签,改用css animation或javascript实现无缝滚动:css需复制内容、动态计算时长、linear缓动;js需requestanimationframe、时间戳计算偏移、touch-action优化移动端。

用 marquee 标签最简单,但别在现代项目里用
它确实能一行代码实现文字滚动:<marquee>欢迎光临</marquee>,支持 direction、scrollamount、loop 等属性。但它是 HTML5 废弃标签,Chrome/Firefox 已移除部分行为(比如暂停悬停失效),Safari 从不支持。SEO 不友好,无障碍(a11y)完全缺失,连基本的键盘焦点都不可控。
如果你只是写个内部测试页或临时演示,它能跑;要是放进生产环境、要兼容屏幕阅读器、或者未来要维护,立刻放弃。
CSS @keyframes + animation 实现真正无缝滚动
核心思路是让元素宽度超出容器,用 transform: translateX() 水平位移,动画结束时瞬间跳回起点——但人眼察觉不到跳变,前提是位移距离和动画时长匹配,且元素内容本身首尾可衔接。
实操要点:
- 容器设
overflow: hidden,避免滚动时出现横向滚动条 - 滚动内容需复制一份拼接(如
文本文本),确保动画末尾与开头视觉一致 - 动画时长不能固定写死,应根据内容长度动态计算:内容越长,滚动越慢才显得“匀速”
- 用
animation-timing-function: linear,禁用缓动,否则速度不均会露破绽
示例片段:
.marquee {
overflow: hidden;
white-space: nowrap;
}
.marquee span {
display: inline-block;
animation: scroll-left 20s linear infinite;
}
@keyframes scroll-left {
0% { transform: translateX(100%); }
100% { transform: translateX(-100%); }
}
JavaScript 控制滚动节奏和交互更可靠
CSS 动画在页面切换、tab 失焦时可能暂停或错帧(尤其 Safari),而 JS 可主动控制播放/暂停/重置。适合需要响应用户操作(如 hover 暂停、点击跳转)的场景。
关键点:
- 别用
setInterval逐像素移动——性能差、易卡顿;改用requestAnimationFrame同步刷新 - 滚动偏移量应基于时间戳计算,而非帧数,避免因帧率波动导致速度不稳
- 监听
mouseenter/mouseleave时,直接修改animation-play-state比重置动画更轻量 - 若内容动态更新(如实时新闻),需重新测量宽度并重置动画状态
一个最小可用逻辑:
const el = document.querySelector('.js-marquee');
let isPaused = false;
function animate() {
if (!isPaused) {
const pos = parseFloat(el.style.transform?.replace(/[^0-9.-]/g, '') || '0');
el.style.transform = `translateX(${pos - 0.5}px)`;
}
requestAnimationFrame(animate);
}
animate();
移动端触摸拖拽和性能陷阱
在 iOS 或 Android 上,纯 CSS 滚动常被系统判定为“非必要动画”,触发降帧甚至强制关闭。用户手指滑动时,原生滚动会劫持事件,导致走马灯卡死或跳动。
绕过方式:
- 给容器加
touch-action: none,阻止浏览器默认手势干预 - 用
passive: false绑定touchmove事件,才能调用preventDefault() - 避免在滚动中频繁读取
offsetWidth或触发重排;所有尺寸计算尽量前置或节流 - 真机测试必做:iOS 的
will-change: transform有时反而引发闪烁,需实测开关
无缝滚动不是“动起来就行”,而是动得稳、停得准、切得顺——最容易被忽略的是内容长度与动画周期的数学关系,算错一点,结尾就露白。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











