骨架屏必须用独立空元素构建,不能复用真实内容容器,否则会导致水合错误、样式污染和无障碍语义噪音;应使用无语义div配专用类名,配合background-position流光动画与明确宽高,并在加载完成时彻底移除DOM。

骨架屏必须用独立空元素构建,不能复用真实内容容器——否则加载完成替换时极易错位、重排或触发水合错误。
骨架屏结构为什么不能复用真实 DOM 节点
常见错误是把 div.title 或 p.content 直接加背景色和动画当骨架用。这会导致三个问题:
- SSR 渲染时骨架和真实内容混在一起,客户端 hydration 会冲突,控制台报
Hydration failed - JS 替换内容时若只改 innerHTML,原有 class、事件监听器可能残留,样式污染风险高
- 无障碍场景下,屏幕阅读器会读出空
p或带aria-label的占位节点,造成语义噪音
正确做法是用无语义的 div 配专用类名,例如:
<div class="skeleton-card"><br> <div class="skeleton-avatar"></div><br> <div class="skeleton-line skeleton-title"></div><br> <div class="skeleton-line"></div><br></div>
CSS 流光动画必须用 background-position 平移
别用 opacity 或 transform 做循环动画——它只是闪烁或抖动,不是“扫描光”。真正有效的流光靠渐变背景横向位移:
立即学习“前端免费学习笔记(深入)”;
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
background-image: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent)-
background-size: 300% 100%(必须 ≥200%,否则位移无效) -
animation: shine 2s infinite linear,关键帧写成from { background-position: 200% 0; } to { background-position: -200% 0; } - 每个骨架元素必须设明确
width和height(或aspect-ratio),否则背景位移区域塌缩,光效跑飞
加载完成时必须彻底移除骨架 DOM
只设 display: none 或 visibility: hidden 是危险操作:
- @keyframes 动画仍在后台运行,长期驻留消耗内存,尤其在 SPA 页面反复进出时
- 骨架节点仍参与布局计算,影响 SSR 水合一致性,可能导致 layout shift
- 若用框架渲染,需确保 unmounted 钩子中调用
element.remove()或replaceWith(realContent)
推荐切换方式:
fetch('/api/data').then(data => {<br> const skeleton = document.querySelector('.skeleton-wrapper');<br> const real = document.createElement('div');<br> real.innerHTML = render(data);<br> skeleton.replaceWith(real);<br>});
SSR 场景下骨架只能客户端注入
服务端不该输出骨架 HTML:
- 骨架是纯视觉占位,无语义、无内容,SSR 输出它会污染 HTML 结构,影响 SEO 和可访问性
- 首屏骨架应在
DOMContentLoaded后 JS 动态插入,或由框架(如 Next.js 的useEffect)控制 - 如果必须 SSR 支持首屏骨架(如提升 FCP),应内联最小骨架 CSS,并确保 hydration 时能精准匹配节点结构
最易被忽略的一点:所有骨架 div 必须不含文本、不设 alt、不带 aria-* 属性——哪怕 aria-hidden="true" 也要显式声明,否则读屏器可能误读为空白块。


















