骨架屏必须放在<body>开始处,紧随<body>标签之后且早于真实内容容器;需用纯CSS实现动画,避免重排;移除时应通过DOM替换而非隐藏,并确保尺寸与层级严丝合缝。

骨架屏该在哪个HTML位置插入
骨架屏必须放在 <body> 开始处,紧随 <body> 标签之后,且早于真实内容容器。如果插在 JS 加载后动态渲染的区域里,用户会先看到空白再闪出骨架,失去意义。
- 正确位置示例:
<body> <div class="skeleton">...</div> <main id="app"></main> </body>
- 错误做法:把骨架屏包裹在
<div id="app">内部,等 Vue/React 挂载后再显示——此时骨架已晚于白屏期 - 服务端渲染(SSR)场景下,骨架结构需和首屏真实 DOM 结构保持宽高一致,否则 CSS 动画会跳变
用纯CSS实现骨架动画的关键属性
不用 JS 控制显隐,靠 opacity + transform + background-image: linear-gradient 模拟加载态,性能最稳。
- 核心动画片段:
.skeleton { background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%); background-size: 200% 100%; animation: loading 2s infinite; } @keyframes loading { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } } - 避免用
transition改变display或visibility,会导致重排;改用opacity+pointer-events: none - 移动端要注意
background-size在 Safari 旧版本中不支持百分比值,建议 fallback 到固定像素如200px 100%
如何安全地移除骨架屏而不触发重绘抖动
骨架屏不是“隐藏”,而是被真实内容自然覆盖——关键在于 DOM 替换时机和 CSS 层叠控制。
- 真实内容渲染完成后,用
document.getElementById('app').replaceWith(realContent),而非innerHTML = ...,避免骨架节点残留导致样式冲突 - 骨架容器必须设
position: relative,真实内容设position: absolute; top: 0; left: 0; width: 100%; height: 100%覆盖其上,确保尺寸对齐 - 若使用 CSS Modules 或 scoped style,骨架和真实内容的 class 名不能共用同一作用域,否则移除时可能误删样式规则
服务端注入骨架屏时的模板陷阱
Node.js 模板引擎(如 EJS、Nunjucks)直接拼接骨架 HTML 很方便,但容易忽略 SSR 和 CSR 的状态一致性。
立即学习“前端免费学习笔记(深入)”;
- 不要在模板里写
<script>document.querySelector('.skeleton').remove()</script>—— 这会在每个请求都执行,且可能因执行时机早于 DOM 就绪而报错Cannot read property 'remove' of null - 推荐做法:服务端只输出骨架 HTML;前端用
DOMContentLoaded或requestIdleCallback延迟移除,确保 DOM 已就绪且主线程空闲 - Next.js / Nuxt 等框架中,骨架屏应仅出现在
getServerSideProps返回的初始 HTML 中,避免客户端 hydration 时重复渲染



















