骨架屏是用CSS模拟结构轮廓的占位技术,核心是linear-gradient动画+固定宽高+无障碍设计,需与真实DOM一致且轻量以避免性能损耗。

骨架屏不是靠 HTML 本身实现的,而是用 CSS 模拟出结构轮廓,在真实内容加载完成前占位。直接写一堆 <div> 并加 background-color 和 border-radius 就能跑起来,但关键在“不干扰可访问性”和“不阻塞首屏渲染”。
怎么用纯 CSS 写一个可用的骨架屏
核心是用 background-image 或 linear-gradient 做动态灰度条,配合 animation 模拟加载流动感;所有骨架元素必须设 width、height 和 overflow: hidden,否则会撑开布局。
常见错误现象:骨架元素高度为 0、文字区域被骨架遮盖、动画卡顿、SSR 下闪烁。
- 用
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%)配合background-size: 200% 100%+animation: loading 2s infinite - 避免给骨架元素设
content或伪元素文字,否则影响屏幕阅读器 - 图片占位区优先用
aspect-ratio(现代浏览器)或padding-top百分比 hack 保宽高比
Vue/React 里怎么控制骨架屏显隐时机
不能等 mounted 或 useEffect 才显示骨架——此时 JS 可能还没执行完,用户看到白屏。得靠服务端或构建时注入初始状态,或用 document.readyState === 'loading' + setTimeout 微调。
立即学习“前端免费学习笔记(深入)”;
使用场景:列表页、详情页、带图片的卡片流。
- Vue 中推荐用
v-if绑定一个loading响应式变量,初始值为true,在onMounted后触发数据请求,请求 resolve 后置为false - React 中避免在
useEffect里直接设setState显示骨架,应提前在组件顶层声明const [loading, setLoading] = useState(true) - 关键点:骨架屏 DOM 必须和服务端返回的结构一致(比如同级有 3 个
.card,骨架也得有 3 个对应容器),否则 hydration 会错位
为什么骨架屏有时比 loading 图标还慢
因为开发者常把骨架屏当“美化版 spinner”,套在整页外层,结果骨架自身样式复杂、动画层级高、甚至嵌了 SVG,反而拖慢渲染。骨架屏要轻——它只是视觉占位,不是功能组件。
性能影响明显的情况:大量 box-shadow、多层 filter: blur()、未压缩的内联 SVG、CSS 动画触发重排。
- 禁用
transform以外的动画属性(如left、top);用will-change: transform提前提示合成 - 骨架元素不用
display: flex嵌套过深,改用grid或绝对定位减少计算量 - 如果页面首屏有 5 张图,骨架里就只画 5 个占位框,别为了“看起来丰富”加额外装饰元素
最易被忽略的是字体闪动:骨架屏消失瞬间,真实文字加载可能触发 FOIT/FOUT。解决办法不是加延迟,而是确保字体资源在 HTML 中预加载,且骨架容器与真实内容用同一套 font-family 和 line-height,让尺寸尽可能对齐。



















