用 CSS @keyframes + transform 可实现平滑无缝滚动公告栏,无需 JS、jQuery 或已废弃的 <marquee> 标签;核心是内容尺寸翻倍配合 translateX/Y 线性无限动画,并按条数动态计算时长。

直接用 CSS @keyframes + transform 就能实现平滑、无 JS 依赖的实时滚动公告栏,不需要学 jQuery、不用写定时器、更别碰已废弃的 <marquee> 标签。
为什么不用 <marquee> 标签
这个标签在 HTML5 中已被明确废弃,Chrome/Firefox/Safari 等现代浏览器虽仍能渲染,但不保证行为一致(比如 scrolldelay 在 Safari 下失效),且无法用 CSS 控制动画曲线、暂停交互或适配响应式。W3C 官方文档里查不到它,只作为“历史兼容项”存在。
-
<marquee behavior="scroll">在部分移动端 WebView 中完全不触发滚动 - 无法通过 JS 获取滚动位置或监听到达边界事件
- 所有样式(如阴影、圆角、渐变)必须靠包裹元素模拟,结构臃肿
CSS 动画滚动的核心写法
关键不是“怎么动”,而是“怎么无缝循环”。靠的是让内容块宽度/高度翻倍,并用 transform: translateX() 或 translateY() 拉动,再配合 animation-timing-function: linear 和 infinite 循环。
- 左右滚动:用
white-space: nowrap防换行,display: inline-block让内容不折行撑宽,animation从100%移到-100% - 上下滚动:每条
<li>高度固定(如line-height: 36px),.scroll-content总高设为单条高度 × 条数 × 2,动画从0到-单条高度 × 条数 - 动画时长要匹配内容量:
animation-duration: 8s对 4 条公告较稳;条数增加,时长也得加,否则会“闪跳”
示例(左右滚动):
立即学习“前端免费学习笔记(深入)”;
#marquee { overflow: hidden; }
#marquee-content {
display: inline-block;
animation: scroll 12s linear infinite;
}
@keyframes scroll {
from { transform: translateX(100%); }
to { transform: translateX(-100%); }
}
JS 介入的必要场景与写法
纯 CSS 滚动适合静态公告;一旦需要“鼠标悬停暂停”“点击跳转”“动态增删公告”,就必须用 JS 控制 animation-play-state 或重置 transform。
- 暂停:给容器加 class
.paused,CSS 写.paused { animation-play-state: paused; } - 动态追加:用
element.innerHTML += "<li>新公告</li>"后,必须重新计算并设置scroll-content的总高度,否则动画终点错位 - 避免 layout thrashing:不要在循环中反复读取
offsetHeight,先缓存值再批量更新
常见错误:document.querySelector('.notice').style.animation = "none" —— 这会清空整个动画定义,恢复后需手动重赋值,正确做法是切 class。
移动端适配和性能注意点
在 iOS Safari 和 Android Chrome 上,transform 滚动比 margin-top 或 scrollTop 更流畅,但仍有坑:
- 务必加
will-change: transform触发 GPU 加速,否则长内容滚动卡顿明显 - 避免在
@keyframes里写left/top,这些属性会触发重排(reflow),而transform只重绘(repaint) - 文字过长时,
text-overflow: ellipsis在动画中可能失效,改用mask-image或伪元素遮罩更可靠
最易被忽略的一点:动画时间不能写死成 10s。如果公告内容从 3 条变成 10 条,还用 10s,用户根本来不及读完第一条——得按内容量动态算时长,比如 duration = 2.5s × itemLength。



















