直接用@keyframes+translateX()可实现跑马灯,但需对齐内容复制、位移基准(推荐translateX(-50%)配合双份内容)、timing-function(须用linear)、iOS合成层触发(拆行写translateZ(0))四点,否则必跳帧、露白或失效。

直接用 @keyframes + transform: translateX() 就能做,但 90% 的人写出来会跳帧、露白、iOS 上不动——问题不在会不会写动画,而在内容复制、位移基准、animation-timing-function、iOS 合成层触发这四点没对齐。
为什么 translateX(-100%) 一循环就闪一下
因为 -100% 是相对于元素自身宽度,不是容器可视区宽度。单份文本滚动完,动画重置回 translateX(0),内容突然跳回起点,视口中间裸露一帧空白——尤其在高刷屏或 iOS Safari 上特别明显。
-
translateX(-100%)≠ “滚满一屏”,它只是“滚掉自己那么宽” - 文本长度不整除容器宽时,末尾必然留白或拖尾
- 动画默认
ease时序,起步慢、收尾又慢,人眼一看就是“一顿一顿”
必须复制内容,且不能有空格
真正无缝靠的是“第二段已在路上”,不是靠动画参数硬撑。HTML 里得手动拼两份相同内容,紧挨着写,中间不能有空格、换行或注释,否则多出间隙。
- 结构示例:
<div class="marquee-content">新闻1新闻2新闻3新闻1新闻2新闻3</div> - CSS 中设
white-space: nowrap+display: inline-block或display: flex横向排列 - 若用 JS 动态渲染(如 React/Vue),必须同步复制 DOM 节点,不能只复制字符串再
innerHTML插入
translateX(-50%) 才是响应式安全写法
当内容总宽 ≈ 容器宽度 × 2 时,translateX(-50%) 才能确保第一份完全移出、第二份刚好完全进画框。这个百分比是相对于父容器宽度的,不随设备变化,比写死 px 或 vw 可靠得多。
立即学习“前端免费学习笔记(深入)”;
- 错误:
transform: translateX(-600px)→ 换屏幕就错位 - 正确:
@keyframes scroll { 0% { transform: translateX(100%); } 100% { transform: translateX(-50%); } } - 配套必须加:
animation: scroll calc(1s * var(--speed, 20)) linear infinite,用 CSS 变量控制速度更灵活
iOS Safari 卡顿/闪烁的硬性避坑点
iOS WebKit 对纯 translateX 有已知渲染缺陷,尤其低电量模式下。最稳妥的解法是拆开声明,并触发合成层:
- 别写:
transform: translateX(0) translateZ(0)→ iOS 会忽略translateZ(0) - 要写成两行:
transform: translateX(0); transform: translateZ(0); - 加
will-change: transform提前告知浏览器该元素将动画,但别滥用,仅加在动画容器上 - 首次播放闪一下?用负
animation-delay对齐起始帧,例如animation-delay: -5s(不能超过总时长)
最容易被忽略的其实是 white-space 和 display 的组合:white-space: nowrap 必须配 display: inline-block 或 flex,否则换行会破坏宽度逻辑;而 overflow: hidden 必须加在容器上,漏掉就露白。



















