首屏骨架屏是用纯css(如linear-gradient)模拟内容区块的灰度占位结构,因体积小、无请求、可缩放、动画可控而优于图片或svg;其核心是两层渐变叠加,需分离background-image、设固定background-size、用background-position动画而非transform,并注意移动端vw适配、opacity切换显隐及光效方向与阅读习惯一致。

什么是首屏骨架屏,为什么用 linear-gradient 而不是图片或 SVG
首屏骨架屏本质是用纯 CSS 占位 + 模拟内容区块的视觉灰度结构,等真实数据加载完再替换。不用图片或 SVG 是因为:体积小、无请求、可缩放、动画可控;而 linear-gradient 配合 background-position 动画,能低成本模拟“扫描光效”,比 clip-path 或多层遮罩更轻量、兼容性更好(iOS Safari 12.2+、Android Chrome 62+ 均支持)。
linear-gradient 骨架屏的关键写法和参数陷阱
核心是用两层渐变叠加:一层静态灰色背景,一层带透明度的动态扫描光条。常见错误是直接写 background: linear-gradient(...) 单值,导致光效不移动或闪烁。
- 必须用
background-image分离两层,避免被覆盖:background-image: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%), linear-gradient(90deg, rgba(255,255,255,0) 0%, rgba(255,255,255,0.3) 50%, rgba(255,255,255,0) 100%);
-
background-size必须设为固定宽度(如200px 100%),否则在不同屏幕下光条拉伸失真 -
background-position初始值建议设为-200px 0,让光条从左外侧开始,避免首帧突兀出现 - 动画必须用
background-position的 x 轴位移,不能用transform——后者会触发重排,且在部分安卓 WebView 中失效
移动端适配要点:rem、viewport 和动画性能
骨架屏区域需随视口缩放,但 linear-gradient 的 background-size 默认是像素单位,直接写 20rem 在 iOS Safari 下不生效(仅 Firefox 支持 rem 单位的 background-size)。
- 推荐方案:用
vw单位,例如background-size: 120vw 100%,配合max-width: 100%限制上限 -
viewportmeta 必须包含width=device-width, initial-scale=1,否则 iOS 上vw计算异常 - 动画帧率易掉:把骨架容器设为
will-change: background-position(仅对动画元素加),或改用transform: translateZ(0)触发 GPU 加速(注意别滥用,可能增加内存) - 避免在
:root或全局 class 上加骨架动画,应只作用于具体骨架容器,比如.skeleton-card
如何与 React/Vue 组件联动控制显隐
骨架屏不是一直显示,得配合数据加载状态切换。关键点在于:不要用 display: none 切换,它会中断动画、触发重排;也不要靠 JS 动态插入 class,容易竞态。
- 推荐用
opacity: 0 / opacity: 1+pointer-events: none控制交互与过渡,搭配transition: opacity 0.2s ease-out - Vue 中可在
v-if外层包一层过渡组件,React 中用useEffect监听 loading 状态,通过 className 切换(如skeleton--loading→skeleton--loaded) - 务必加
animation-fill-mode: forwards,防止动画结束后背景回退到初始位置,造成闪烁 - 真实内容渲染后,建议给骨架容器加
aria-hidden="true",避免读屏器误读
最常被忽略的是光效方向与文字流方向的一致性:中文阅读习惯从左到右,所以扫描光必须是 90deg(即从左向右扫),若写成 270deg,用户直觉上会觉得“卡顿”或“倒放”。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











