骨架屏应在真实数据加载耗时超过300ms时启用;短于该阈值直接渲染更自然,避免布局抖动与DOM开销;判断依据是responseStart到responseEnd时间,非请求有无。

骨架屏该不该显示?看加载时长再决定
骨架屏不是“有就比没有强”,它只在真实数据加载耗时超过 300ms 时才值得启用。短于这个阈值,直接渲染内容更自然;强行插入骨架屏反而造成布局抖动和额外 DOM 开销。
判断依据不是“有没有网络请求”,而是 fetch 或 axios 的 responseStart 到 responseEnd 时间。可以用 performance.getEntriesByType('resource') 拦截关键请求做统计,而不是凭经验写死 setTimeout。
- 移动端弱网(2G/3G)或 SSR 首屏水合延迟高时,骨架屏收益明显
- 静态资源已缓存、API 响应
- 首次访问用户可默认启用,老用户若历史平均加载
骨架结构必须和真实 DOM 完全对齐
常见错误是骨架元素用 div 占位,但真实内容用 article + header + figure,导致 CSS 选择器失效、高度塌陷、或者 Flex/Grid 容器内子项行为不一致。
正确做法是:骨架 HTML 必须复用真实组件的标签语义和 class 层级。比如真实卡片是 <article class="card"><header><h2>...</h2></header><img></article>,骨架就得写成完全一样的结构,仅把文本和图片替换成 <span class="skeleton-text"></span> 和 <span class="skeleton-img"></span>。
将 Markdown 文章转换为微信公众号兼容的纯 HTML 格式。当用户要求"转成微信格式"、"生成公众号文章 HTML"、"排版到微信草稿箱"、"微信粘贴格式"时触发。输出带内联样式的纯 HTML,微信编辑器可直接渲染,无需额外适配。支持标题、段落、列表、粗体、行内代码、表格、引用块、代码块、配图的完整转换。
立即学习“前端免费学习笔记(深入)”;
- 避免用
display: none切换骨架和真实内容——会导致重排,改用visibility: hidden+opacity: 0过渡 - 所有骨架元素需设置明确的
width/height,不能依赖内容撑开,否则加载后会“弹跳” - 图片占位符必须声明
aspect-ratio或固定宽高,否则响应式断点切换时容易错位
动画不能只靠 background-position 循环
@keyframes shimmer 是最常用方案,但它在 Safari 15.4–16.3 和部分安卓 WebView 中存在动画卡顿甚至不触发的问题。更稳的方式是组合使用 opacity 渐变 + transform: translateX() 位移。
示例关键帧:
@keyframes skeleton-shimmer {
0% {
opacity: 0.6;
transform: translateX(-100%);
}
100% {
opacity: 0.2;
transform: translateX(100%);
}
}
- 动画时长控制在 1.2–1.8s,太快显得浮躁,太慢削弱“正在加载”暗示
- 禁用
prefers-reduced-motion: reduce用户的动画:用@media (prefers-reduced-motion: reduce)关闭 shimmer,只保留静态灰阶 - 不要给所有骨架元素统一加动画——标题行、图片、段落应有不同节奏,模拟真实内容加载顺序
无障碍支持常被忽略但影响上线
屏幕阅读器会把骨架元素当作真实内容朗读,尤其当用了 aria-label 或未清空的 alt 时,会造成严重误导。骨架屏本身应是“视觉专属”,对辅助技术透明。
- 所有骨架元素必须添加
aria-hidden="true" - 禁止在骨架结构中使用
role="heading"、role="img"等语义角色 - 真实内容挂载后,需用
document.getElementById('main-content').focus()主动聚焦到首屏可操作区域,否则键盘用户会卡在不可见的骨架节点上 - 如果页面含表单,骨架期间应禁用
tabindex,防止焦点落入占位区域


















