使用 @keyframes + translateX(-100%) 会闪动,因单组滚动终点(最后一张右边缘)与起点(第一张左边缘)内容不匹配,强行回跳导致视觉断裂;::after 复制整组内容实现无缝衔接,需确保其宽度、结构与原内容完全一致,位移量对应总宽(如5张则为-500%),且 animation-timing-function 必须为 linear,响应式下应通过 CSS 变量或 vw 单位动态控制位移。

为什么直接用 @keyframes + translateX(-100%) 会闪一下
动画终点回到起点时视觉断裂,不是浏览器卡顿,而是内容不匹配:单组图片滚动完,100% 位置显示的是最后一张图的右边缘,而 0% 是第一张图的左边缘。两者图像不同,强行“回跳”必然露白或抽搐。
用 ::after 复制内容,本质是把“衔接点”从动画终点移到内容内部——让动画全程只在两段相同内容之间平滑过渡,避开重置瞬间。
-
::after必须和原内容完全一致(相同宽高、相同子元素结构),否则位移对不齐 - 不能只复制 HTML 内容,必须确保
::after渲染后宽度 = 原始容器总宽,否则translateX(-100%)位移量就错 -
content: ""不行,得用content: attr(data-content)或 JS 注入,但更稳的方式是直接写死结构,::after只补样式
::after 复制图片列表时,width 和 transform 怎么配
假设原始图片共 5 张,每张等宽占容器 20%,那么整个 .slider 宽应为 500%(即 5 × 100%);::after 需撑出同样宽度,且与原内容水平拼接。
- 父容器设
display: flex; flex-wrap: nowrap;,子项(含::after)设flex-shrink: 0; -
::after必须设content: ""+display: block;+ 显式width: 500%;,不能靠继承 - 动画位移终点固定写
transform: translateX(-500%),不是-100%——后者只在单组内有效,这里要拉完全部两组 - 若用
white-space: nowrap,则::after必须是 inline 元素,且父容器需设font-size: 0消除间隙
鼠标悬停暂停时,animation-play-state: paused 为什么仍会抽搐
暂停本身没问题,问题出在恢复:CSS 动画恢复时按剩余时间继续跑,但位移是累积的,translateX 值可能卡在非整数倍图片宽度的位置,导致下一帧错位半张图。
立即学习“前端免费学习笔记(深入)”;
- 真正安全的暂停方式是:悬停时用 JS 记录当前
getComputedStyle(el).transform,恢复时重设transform并重启动画,或改用animation-delay调整起始偏移 - 纯 CSS 方案中,唯一可靠的是让动画周期足够长(如
30s),并配合linear,使暂停点误差肉眼不可辨 -
animation-timing-function: linear必须显式声明,否则某些浏览器默认是ease,首尾减速会让衔接点更敏感
响应式下,100% 宽度到底指谁的百分比
这是最容易被忽略的坑:translateX(-100%) 的 100% 指的是**被动画元素自身的宽度**,不是父容器,也不是视口。如果图片容器宽度随屏幕变化,但动画没重算,位移就会越来越不准。
- 不要用固定
animation-duration配合流式宽度;要么用vw单位写死位移(如translateX(-300vw)),要么用 CSS 变量动态传入宽度值 - 推荐方案:用
calc()把图片数量和单图宽度绑定,例如width: calc(var(--count) * var(--item-width));,再让translateX用同一套变量 - 媒体查询里改
--count或--item-width比重写整个@keyframes更可控


















