骨架屏是用灰色块模拟真实内容布局的占位方案,而非动效加载图标;它通过伪元素渐变背景、结构一致的DOM和display:none切换实现平滑渲染,避免布局跳变,提升用户对内容位置与结构的预期。

什么是骨架屏,为什么不用 loading 图标
骨架屏不是动效图标,而是用灰色块模拟真实内容的布局结构,在数据加载完成前先渲染出“形似”的占位容器。它比 loading 图标更符合用户预期——能明确感知到内容即将出现在哪、有多大、有几行,减少白屏焦虑。关键在于:它必须和最终 DOM 结构高度一致,否则加载后会触发重排或视觉跳变。
用纯 CSS 实现骨架屏的关键技巧
核心是用 ::before 或 ::after 伪元素 + background-image: linear-gradient() 模拟渐变灰阶效果,再配合 animation 让高亮条横向扫过,营造“正在加载中”的视觉暗示。
- 避免直接写死宽高,优先用
width: 100%和aspect-ratio(现代浏览器)或padding-top百分比撑开容器 - 文字行用多个
div模拟,每行高度设为1rem,margin-bottom控制行距,不要用line-height配合空格模拟多行 - 图片区域推荐用
border-radius+overflow: hidden+ 灰色背景,比加img标签更轻量且不触发资源请求 - 动画时长建议设为
1.2s,太短显得急促,太长延迟感明显;用ease-in-out比linear更自然
.skeleton-item {
background-color: #f0f0f0;
}
.skeleton-item::before {
content: '';
display: block;
background: linear-gradient(90deg, transparent, #e0e0e0, transparent);
background-size: 200% 100%;
animation: loading 1.2s infinite;
}
@keyframes loading {
0% { background-position: -200% 0; }
100% { background-position: 200% 0; }
}
Vue/React 中动态控制骨架屏显隐的常见错误
骨架屏不是全局开关,必须和真实组件的加载状态强绑定。最容易踩的坑是:在 data 初始化为空时就渲染骨架,但接口返回空数组或 null 后没及时切换,导致“骨架屏永远不消失”。
- Vue 中慎用
v-if="!data.length"判断,应改为v-if="loading || !data?.length",并确保loading在请求开始时置true,响应后置false - React 中不要把骨架屏写在条件渲染外层,比如
{loading &&是安全的;但}{data && } {data ?会导致首次 data 为: } undefined时误判 - 服务端渲染(SSR)场景下,骨架屏不能出现在首屏 HTML 中,否则会被搜索引擎抓取为真实内容,需用
v-show或display: none控制初始隐藏,等客户端 hydration 后再根据状态显示
如何让骨架屏适配深色模式
骨架屏颜色不是固定写死的 #f0f0f0,而要跟随系统主题变化。CSS 自定义属性 + @media (prefers-color-scheme: dark) 是最稳妥的方式。
- 定义两套变量:
--skeleton-bg: #f0f0f0和--skeleton-bg-dark: #333,在根元素上设置,并在媒体查询中覆盖 - 渐变动画里的中间色也要同步换,比如
linear-gradient(90deg, transparent, var(--skeleton-bg), transparent) - 如果项目用了 CSS-in-JS 或 Tailwind,注意其暗色模式插件是否支持伪元素的变量注入,部分方案对
::before的var(--x)支持不完整
骨架屏真正难的不是画几个灰色块,而是让它和业务组件的生命周期、DOM 结构、主题系统严丝合缝地咬合。一个没对齐的 padding、一次忘记清除的 loading 状态、一段没随主题更新的渐变色,都会让用户瞬间出戏。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











