波浪扫描线骨架屏本质是用 linear-gradient 创建横向平移的渐变遮罩覆盖静态灰块,关键在 background-position 位移而非 DOM 动画;需设大 background-size、合理初始偏移、1.5–2.5s 动画时长及错开 animation-delay 实现自然加载感。

用 background-image + linear-gradient 模拟波浪扫描线
骨架屏的波浪动画本质不是真“动”,而是用渐变色遮罩在静态灰块上,再让遮罩横向平移——视觉上就像光扫过一样。关键不在 DOM 动画,而在背景层位移。
常见错误是直接对 div 做 transform: translateX,结果整个骨架块滑出去,或者用 animation: keyframes 反复改 background-position 却没设好循环起点,导致卡顿或跳帧。
- 必须用
background-image: linear-gradient创建一个高对比度的明暗分界(比如 45deg 方向的深灰→浅灰→深灰) -
background-size要设成宽度远大于容器(如200% 100%),否则平移几像素就循环完了,看不出“扫描”感 -
background-position初始值建议设为-100% 0,让亮区从左侧外开始入场,更符合人眼预期 - 动画时长控制在
1.5s–2.5s最自然;太快像闪,太慢像卡
background-clip: text 不适用,别往文字骨架上硬套
有人想给文字型骨架(比如 <span class="skeleton-text"></span>)加波浪效果,试图用 background-clip: text 配合渐变动画。这会出问题:骨架文本通常没内容、没字体渲染,background-clip: text 在多数浏览器里直接失效,尤其 Safari 和旧版 Chrome。
正确做法是放弃“文字遮罩”,统一用块级元素模拟文字行高和宽度,再套波浪背景。例如:
立即学习“前端免费学习笔记(深入)”;
.skeleton-line {
height: 1.2em;
background: #e0e0e0;
background-image: linear-gradient(90deg, transparent, #c0c0c0, transparent);
background-size: 200% 100%;
background-position: -100% 0;
animation: wave 2s infinite;
}
这样兼容性好,且能精准控制每行扫描节奏。
移动端要注意 will-change: background-position 的副作用
加了这个声明确实能提升动画流畅度,但 iOS Safari 有个老 bug:如果父容器有 overflow: hidden,will-change 会导致背景平移错位,扫描线突然断开或偏移半截。
实操建议:
- 优先用
transform: translateZ(0)替代will-change触发硬件加速(更稳妥) - 若必须用
will-change,只在动画开始前动态加,结束立即移除(用 JS 控制element.style.willChange) - 在 iPhone 上务必真机测试,模拟器常测不出错位
多段骨架不同步?用 animation-delay 错开起始时间
一排多个骨架块(比如头像+三行文字+按钮)如果都用相同 animation,会一起亮一起暗,失去真实加载感。解决方法不是写多个 keyframes,而是用 animation-delay 微调。
例如:
- 头像:
animation-delay: 0s - 第一行文字:
animation-delay: 0.2s - 第二行:
animation-delay: 0.4s - 按钮:
animation-delay: 0.6s
延迟值控制在 0.1–0.3s 区间最自然;超过 0.5s 就显得拖沓,用户会觉得“怎么还没出来”。
真正难的不是写对那几行 CSS,而是波浪角度、渐变停靠点、位移速度这三者的组合要刚好落在人眼识别“正在加载”的临界区间——差 5 度或快 0.3 秒,就从“流畅”变成“诡异”。调的时候别只看代码,盯着预览界面盯 10 秒,感觉对了再停。










