应改用 css transform 动画替代 js 滚动控制:水平滚动用 @keyframes + translatex(),上下滚动用 translatey(),配合 animation-play-state 实现悬停暂停,避免重排,利用合成层提升性能。

Chrome 报 “Unable to preventDefault inside passive event listener” 怎么办
这是新版 Chrome(≥56)对 touchstart / wheel 事件的强制限制:默认把它们设为 passive: true,即禁止在监听器里调用 preventDefault()——而老式滚动文字(比如靠 setInterval + scrollTop 模拟的)常偷偷阻止默认滚动来“抢权”,直接被拦住并报这个警告。
根本解法不是硬加 passive: false(那会阻塞主线程、卡顿明显),而是彻底放弃手动控制滚动行为,改用纯 CSS transform 动画驱动位移:
- 动画走合成层(compositor),不触发重排重绘,性能稳
- 完全绕过事件监听,自然规避
passive限制 - 不需要 JS 控制节奏,浏览器自己调度帧率,更省心
用 @keyframes + translateX() 实现无缝水平滚动
核心是让文字从右往左匀速平移,且首尾衔接不露白。关键不在“动”,而在“怎么动得看不出断点”:
- 容器必须设
overflow: hidden和固定宽高,否则动画溢出不可控 - 文字元素需
white-space: nowrap+display: inline-block(否则transform对内联文本无效) - 动画起点设
transform: translateX(100%)(文字完全在容器右侧外),终点设transform: translateX(-100%)(完全移出左侧外) - 动画时长要足够长(如
20s),否则人眼能感知“闪回”;若内容短,可复制一遍文本或用伪元素补位
示例片段:
立即学习“前端免费学习笔记(深入)”;
@keyframes scrollText {
from { transform: translateX(100%); }
to { transform: translateX(-100%); }
}
.scrolling-title {
display: inline-block;
white-space: nowrap;
animation: scrollText 20s linear infinite;
}
上下滚动文字别用 top 或 margin-top
很多老教程还教用 top 或 margin-top 配合 position: absolute 做上下跑马灯,这在新版 Chrome 里会严重掉帧——因为每次修改 top 都触发重排(layout),浏览器必须重新计算整个布局树。
正确做法是只用 transform: translateY():
- 它只影响绘制层(paint layer),不牵扯布局,GPU 可直接加速
- 配合
will-change: transform或强制创建合成层(如加transform: translateZ(0))效果更稳 - 动画关键帧写法同理:
from { transform: translateY(0); } to { transform: translateY(-100%); }
注意:如果滚动区域高度固定,-100% 是指文字自身总高度,不是容器高度——得用 JS 算或用两份内容拼接来保循环。
鼠标悬停暂停、点击跳转等交互怎么加
纯 CSS 动画默认没法暂停,但现代浏览器支持 animation-play-state,配合伪类就能响应用户操作:
- 给滚动元素加
animation-play-state: running默认态 - 写
.scrolling-title:hover { animation-play-state: paused; }即可悬停暂停 - 若需点击跳转,直接给整个容器加
<a href="..."></a>包裹,不影响动画(a是行内元素,记得设display: block或inline-block) - 避免在
hover里改transform值(比如突然 rotate),容易打断动画节奏;真要动效,单独定义新动画类切换
真正难的不是让字动起来,而是让动得“不费力”——Chrome 的限制本质是在逼你用对的方式做事:少碰 layout,多走合成层,把控制权还给浏览器渲染管线。











