卡片骨架必须严格复用真实DOM结构和类名,确保hydration成功;禁用动态class、图片占位须用aspect-ratio或padding-top hack;扫描动画仅改background-position;骨架需卸载而非隐藏;首屏骨架须内联HTML。

卡片骨架必须复用真实DOM结构和类名
骨架不是“画个差不多的图”,而是要让浏览器在内容加载前,就渲染出和最终卡片完全一致的布局树。一旦标签名、class、嵌套层级或子节点数量不一致,hydration 就会失败——React/Vue 会丢弃整个骨架节点并重挂载,结果就是表单清空、焦点丢失、CLS 指标飙升。
- 真实卡片是
,骨架就得严格写成标题
- 禁用动态 class:
class="card {{ loading ? 'skeleton' : '' }}"是危险写法;应固定为class="card skeleton-card",靠 CSS 控制显隐 - 用
document.querySelector('.card').outerHTML对比服务端 HTML 和客户端 hydrate 后 DOM,能快速定位结构偏移点
图片占位必须用 aspect-ratio 或 padding-top hack
用 或 height: 100% 做图片占位,90% 的情况会导致骨架“消失”——父容器无高度时,height: 100% 计算为 0,真实图片插入后立刻触发 layout shift。
- 现代方案:给图片容器设
aspect-ratio: 16 / 9+width: 100%+overflow: hidden - 兼容旧浏览器:用
padding-top: 56.25%+position: relative+ 子元素position: absolute; top: 0; left: 0; width: 100%; height: 100% - 绝对禁止在骨架中使用
标签——哪怕只是 data URI,也会触发解码逻辑,占用主线程
linear-gradient 动画只改 background-position,别碰其他属性
扫描光效的本质不是“变色”,而是“光扫过”。用 transform 或 opacity 动画模拟,容易在 iOS Safari 或低端安卓 WebView 中掉帧甚至静止;而 background-position 位移是 GPU 合成友好的动画方式,且不触发重绘。
- 关键 CSS:
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%)+background-size: 200% 100%+background-position: -200% 0 - @keyframes 只写:
@keyframes loading { 0% { background-position: -200% 0; } 100% { background-position: 200% 0; } }—— 不改颜色、不调 size、不用 ease-in-out(停顿感破坏扫描直觉) - 加
will-change: background-position,避免 Chrome 某些版本闪烁
骨架必须卸载,不能靠 display: none 隐藏
很多项目把骨架节点设为 display: none 或 visibility: hidden,以为“隐藏了就没事”。但这些节点仍在 DOM 中参与布局计算、占用无障碍树、拖慢页签性能,SSR 场景下 hydration 更会错位。
- 数据加载完成,必须调用
skeletonEl.remove(),而不是skeletonEl.style.display = 'none' - 如果骨架由 Web Component 渲染,要在
disconnectedCallback中清除所有动画句柄 - 首屏骨架必须内联在 HTML 中下发——等 JS 执行完再注入,用户先看到白屏,再闪出骨架,最后才出现真实内容,“白→灰→实”三段式渲染会让 LCP 和 CLS 直接恶化
实际中最容易被忽略的,是骨架与真实内容之间那层“像素级对齐”的责任:宽高、行高、圆角、内外边距,全都得一一对上。差 1px,就可能在某些设备上触发重排;少一个子节点,hydration 就会放弃整棵树。这不是样式问题,是结构契约。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











