纯CSS骨架屏应使用linear-gradient配合background-position动画实现光效移动感,而非opacity闪烁;渐变色推荐transparent与rgba(0,0,0,0.08)组合,背景尺寸设为200%以上,动画时长1.8s,错峰延迟0.2s~0.4s,并避免background-attachment:fixed。

用 linear-gradient 搭配 background-position 实现骨架屏闪烁
纯 CSS 骨架屏的核心不是“闪烁”,而是模拟内容加载时的渐变光效移动感。直接用 opacity 闪会显得生硬,且与真实加载体验脱节。推荐用带方向的线性渐变背景 + 动画位移,视觉上更接近原生 App 的骨架效果。
关键点在于:渐变色要从亮到暗(比如 #f0f0f0 → #e0e0e0),再叠加一个透明度变化的遮罩层(或直接用 to right 方向 + 宽度足够大的渐变区域),让“光扫过”的感觉自然。
- 动画必须用
background-position,不能用transform或left,否则会触发重排,影响滚动性能 - 渐变宽度建议设为
200%或更大,确保位移过程平滑无跳变 - 动画时长控制在
1.5s~2s,太快显得急促,太慢失去加载暗示感
@keyframes 中避免写死颜色值,用 transparent 和变量兼容暗色模式
如果项目支持暗色模式,硬编码 #f0f0f0 会导致骨架在深色背景下不可见。更稳妥的做法是用 transparent 起始色 + currentcolor 或 CSS 自定义属性控制亮度层级。
示例动画定义:
立即学习“前端免费学习笔记(深入)”;
@keyframes skeleton-loading {
0% {
background-position: -200% 0;
}
100% {
background-position: 200% 0;
}
}
然后在元素上这样用:
.skeleton {
background: linear-gradient(90deg, transparent, rgba(0,0,0,0.08), transparent);
background-size: 200% 100%;
animation: skeleton-loading 1.8s infinite;
}
-
rgba(0,0,0,0.08)比固定灰阶更适应不同背景,尤其在浅色/深色主题切换时仍可见 - 不要用
background-image: linear-gradient(...)单独声明,而要用简写的background,否则background-size和background-position可能失效 - 动画名别起成
loading这种泛名,容易和其它组件冲突,建议加前缀如skeleton-loading
多个骨架元素同时动画时,用 animation-delay 错峰避免“齐闪”感
一排卡片或列表项如果所有骨架都同一时间开始动画,会显得机械、不真实。人眼对节奏差异很敏感,错开 0.2s~0.4s 的延迟就能大幅提升拟真度。
- 可用 CSS
:nth-child(n)批量加延迟:&:nth-child(2) { animation-delay: 0.2s; } - 如果骨架结构动态生成(比如 Vue/React 列表),优先在 JS 层给每个骨架元素加
style="--delay: 0.3s",CSS 里用animation-delay: var(--delay); - 延迟值不宜超过
0.6s,否则首屏部分骨架停顿太久,用户可能误判为卡死
移动端 Safari 下 background-attachment: fixed 会禁用动画,务必禁用该属性
某些骨架方案为了模拟“光扫过”的纵深感,会尝试加 background-attachment: fixed。但在 iOS Safari(尤其是 15.x 及更早版本)中,这会导致 background-position 动画完全失效——页面静止,骨架不动。
- 检查所有骨架类是否意外继承了父级的
background-attachment,显式重置为scroll或直接不设 - 真机调试时重点看 iOS 设备,模拟器有时不复现此问题
- 若必须做视差效果,改用伪元素 +
transform: translateX(),但要注意开启will-change: transform防止闪屏
最易被忽略的是:动画本身没问题,但某个全局 reset.css 里写了 background-attachment: fixed,结果整站骨架全失效。查不到原因时,先看 computed style 里的 background-attachment 值。


















