纯CSS图片轮播核心是用@keyframes控制opacity与z-index实现透明切换,而非transform位移;所有图片需absolute定位重叠,共用同一动画,仅通过负延迟错开显示时机,配合steps(1,end)硬切避免透出,交互功能必须JS辅助。

怎么用 @keyframes 做图片透明切换
纯 CSS 轮播的核心不是“移动”,而是控制多张图的 opacity 和 z-index 层叠顺序。动画本身只负责按时间点切换透明度,不涉及 transform 位移——这样更轻量,也避免 Safari 上 transform 触发重排导致卡顿。
常见错误是把所有图都设 opacity: 1,或忘了加 position: absolute 让它们重叠。结果就是图片堆成一摞,或者只显示第一张。
-
@keyframes每个关键帧只设一张图opacity: 1,其余为0 - 所有图片必须包裹在
position: relative的容器里,自身设position: absolute; top: 0; left: 0; - 动画时长要匹配总图数 × 单图停留时间(比如 3 张图、每张停 4s,总周期就得 12s)
```css
@keyframes fade {
0% { opacity: 1; }
33% { opacity: 0; }
66% { opacity: 0; }
100% { opacity: 0; }
}
```
animation-timing-function 选 steps() 还是 ease-in-out
用 opacity 切换时,ease-in-out 会让过渡“软”但容易糊:两张图同时半透明,背景透出来,观感脏。而 steps(1, end) 是硬切,适合轮播这种非渐进场景。
但注意:steps() 只对离散状态切换有效;如果你用 opacity + transition(非 animation),它就不起作用——steps() 是 animation-timing-function 的值,不是 transition-timing-function 的。
立即学习“前端免费学习笔记(深入)”;
- 轮播用
animation→ 选steps(1, end)避免重叠透出 - 如果图多(>5 张),
steps()在低性能设备上可能掉帧,可降级为linear - 别在
transition里写steps(),浏览器会忽略
为什么不能只靠 :nth-child() 控制每张图的动画延迟
因为 animation-delay 是静态的,一旦设死就无法循环——第 1 张延时 0s,第 2 张 4s,第 3 张 8s……到第 4 轮时,第 1 张又要从 12s 开始延时,但 CSS 没法动态算这个。
真正可行的是单个 @keyframes 定义完整周期,所有图共享同一动画,仅靠关键帧位置错开显示时机。否则你得手写几十行 nth-child 规则,维护成本爆炸,且无法响应图数量变化。
- 每张图的
animation属性必须完全一致(同名动画、同时长、同 iteration-count) - 区别只在
animation-delay:第 n 张 =-(n-1) * 单图时长,负延迟让它从周期中间开始播 - 容器加
animation-iteration-count: infinite,否则播完一轮就停
移动端点击暂停/手动切换为什么很难纯 CSS 实现
纯 CSS 没法监听点击或触摸事件,:hover 在 iOS 上不可靠(需点击两次才触发),:active 只维持毫秒级。所以“点一下暂停”“左右箭头切换”这类交互,CSS 本身做不到。
有人用 input[type="checkbox"] + label 模拟开关,但只能做暂停/播放二态,没法做“下一张”。而且 checkbox 状态无法被 JS 外部控制,和用户实际操作脱节。
- 需要交互 → 必须引入少量 JS,哪怕只控制
animation-play-state - 若坚持零 JS,只能接受自动轮播,且无法响应用户停留页面时长(比如用户切到其他 tab,动画仍在后台跑)
- 安卓 WebView 对
animation-play-state支持不稳定,iOS 更好些,但仍有兼容性缺口
最易被忽略的一点:轮播图的 img 标签没加 loading="lazy",首屏加载时会一次性拉取全部图片,尤其在弱网下明显卡顿。该属性不影响动画逻辑,但直接影响用户第一眼体验。


















