骨架屏是内容加载前的结构占位,用html/css实现与真实dom尺寸一致的灰色占位元素,配合扫描动画降低感知延迟,需服务端直出且避免js动态插入。

什么是骨架屏,为什么不用 loading 图标
骨架屏不是装饰,是内容加载前的结构占位——它告诉用户“这里会有一张图、三行文字、一个按钮”,而不是“请等待”。相比 loading 图标,骨架屏能降低感知延迟,尤其在首屏内容结构固定时(比如新闻列表、商品卡片),用户不会因空白而误判页面卡死。
关键点在于:骨架屏必须和真实 DOM 结构尺寸一致,否则加载后会闪动;它得是纯 HTML/CSS 实现,不能依赖 JS 渲染,否则失去意义。
用 CSS 伪元素 + transparent 模拟骨架效果
最轻量、兼容性最好的方式:不引入额外 DOM 节点,用 ::before 或 ::after 绘制灰色块,配合 background-image: linear-gradient 做扫描光效。
- 给容器加
class="skeleton",再用 CSS 控制伪元素高度/宽度/圆角(如头像用border-radius: 50%) - 扫描动画用
@keyframes移动渐变背景,注意background-size要设为200% 200%才能平滑滚动 - 别用
opacity: 0.3叠加在真实内容上——这会导致加载后重绘闪烁;应让骨架屏和真实内容用visibility: hidden / visible切换,或用display: none / block - 移动端要注意
transform: translateZ(0)触发硬件加速,避免扫描动画掉帧
Vue/React 中如何自动注入骨架屏 HTML
手写骨架结构易错且难维护,推荐用编译时方案:在构建阶段把组件模板分析出来,自动生成对应骨架 HTML 片段。
- Vue 项目可用
v-skeleton插件,或基于vue-template-compiler提取v-if/v-for节点,生成带class="skeleton-item"的占位结构 - React 推荐
react-loading-skeleton,它通过<skeleton count="{3}"></skeleton>动态生成,但要注意:服务端渲染(SSR)时需确保骨架 HTML 在首屏直出,否则会有水合 mismatch - 切记不要在
useEffect或mounted里动态插入骨架 DOM——这会让骨架屏晚于白屏出现,失去价值
服务端直出骨架屏的关键细节
真正发挥骨架屏价值的场景,是首屏 HTML 里就包含骨架结构,而非等 JS 加载完才渲染。这意味着骨架 HTML 必须和服务端模板强绑定。
- Next.js 用户可在
getServerSideProps返回数据前,用renderToStaticMarkup预生成骨架 HTML 字符串,插入到页面初始innerHTML中 - Nuxt3 使用
serverComponents时,骨架模板应放在server/components/下,确保只在服务端解析 - 如果用了 CDN 缓存,要确认骨架屏 HTML 不被缓存成“永久占位”——建议对骨架节点加
data-skeleton="true"属性,JS 加载后立刻移除,避免缓存污染
最难处理的是响应式骨架:同一组件在 PC 和手机下结构不同,但服务端无法知道 UA。稳妥做法是只对首屏固定结构做骨架,其余区域用 JS 懒加载 + 客户端骨架补全。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











