纯CSS无缝滚动必须复制内容并精确位移,单份内容用translateX(-100%)会露白;横向推荐flex+双份内容+translateX(-50%),纵向需固定行高与容器高度对齐,hover暂停用animation-play-state最可靠。

直接用 @keyframes + transform: translateX() 就能实现,但 90% 的人做出来会跳帧、露白或 iOS 上不动——问题不在会不会写动画,而在四个关键点没对齐:内容复制、位移基准、timing function、iOS 合成层触发。
为什么 translateX(-100%) 会露白或卡顿?
因为这里的 -100% 指的是元素自身宽度,不是容器可视区宽度。文本长度不整除容器宽时,动画播完跳回起点,第二段内容没顶上来,就露出空白。
-
translateX(-100%)≠ “滚满一屏”,只是“滚掉自己那么宽” - 单段文本永远无法视觉无缝;必须至少复制一次内容(文案文案)
- 若文本过短,
-100%可能还没移出视口就结束了;过长则末尾拖尾
位移值该设多少?不能硬写像素
要让第二段开头刚好接上第一段结尾,位移距离必须等于容器宽度。但响应式下容器宽会变,所以不能写死 translateX(-300px)。
- 推荐方案:
translateX(-50%),前提是内容已复制两次,并用display: inline-block或display: flex横向排列 - 原因:两段并排总宽 ≈ 200%,位移 -50% 后,第二段刚好完全进入视口,第一段完全移出
- 别把
translateX(0)和translateZ(0)写在同一行,iOS Safari 会忽略后者;要拆成两条声明
animation-timing-function 必须显式设为 linear
默认的 ease 会让动画起步慢、中间快、收尾又慢,人眼一看就是“一顿一顿”,根本不像匀速滚动。
立即学习“前端免费学习笔记(深入)”;
- 错误写法:
animation: scroll 12s infinite;(没声明 timing function,走浏览器默认) - 正确写法:
animation: scroll 12s linear infinite;或外层加animation-timing-function: linear - 即使
@keyframes里只写了from/to,也不能省略linear——它控制播放节奏,不是插值方式
首次播放闪一下?加负 delay 对齐起始帧
动画默认从 0% 开始,但内容初始位置未必对齐视觉起点,导致第一帧明显偏移。
- 比如总时长 30s,想让它从第 10s 状态开始显示,就设
animation-delay: -10s - 浏览器会直接跳转到该时间点对应的关键帧,视觉上就是“自然滚动中”
- 负 delay 值不能超过动画时长,否则行为未定义(多数浏览器取模或回退)
- 动态内容场景下,需 JS 重新计算总宽后重设
animation-duration和animation-delay
最易被忽略的其实是 white-space 和 display 组合:white-space: nowrap 必须配 display: inline-block 或 flex,否则换行或块级行为会破坏宽度逻辑,再怎么调位移都没用。


















