纯css骨架屏用background-image配合linear-gradient模拟色块,加background-position动画实现流动效果;需设visibility:hidden避免重排,注意ios对background-clip:text兼容性问题。

HTML里怎么用纯CSS实现骨架屏
不用JavaScript也能做骨架屏,关键在用background-image配合linear-gradient模拟色块占位,再用animation加个渐变移入效果。适合静态内容区域,比如文章标题、头像、段落占位。
常见错误是直接写死高度/宽度,导致响应式断层;或者动画只设infinite没配ease,看起来卡顿。
- 给骨架容器设
display: inline-block或flex,避免父容器塌陷 - 用
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%)+background-size: 200% 100% - 动画写成
background-position: 200% 0; animation: loading 1.5s infinite ease,比translateX更轻量 - 别对
img标签直接套骨架——应该用div模拟,等真实图片加载完再opacity: 0 → 1切换
Vue/React项目中骨架屏怎么和真实数据联动
骨架屏不是摆设,得等接口返回、组件挂载完成再隐藏。否则会闪一下空白,体验反而更差。
核心是控制显示时机:Vue用v-if配合data.loading,React用loading ? <skeleton></skeleton> : <realcontent></realcontent>。但容易忽略的是“加载完成”的定义边界。
立即学习“前端免费学习笔记(深入)”;
- 接口404或500也算“加载完成”,骨架屏必须收掉,否则用户以为卡死了
- 列表页建议按
item粒度控制骨架,而不是整个list——用v-for渲染骨架项,再用key绑定真实id,Vue能自动复用DOM - SSR场景下,服务端不执行JS,骨架屏要和服务端首屏HTML一起输出,否则客户端水合前会白屏
- React里别在
useEffect里才设置loading = false,应从请求发起时就置为true,避免竞态
为什么用visibility: hidden比display: none更适合骨架屏切换
因为骨架屏占位结构要和真实内容保持一致的盒模型。用display: none会让父容器重排,导致页面跳动;而visibility: hidden保留空间,只是不可见。
但很多人不知道visibility有继承性——子元素默认也会被隐藏,所以得手动给真实内容加visibility: visible覆盖。
- 骨架容器用
visibility: hidden,真实内容用visibility: visible,两者共存不冲突 - 如果骨架用了
opacity: 0,注意它仍会响应事件(如点击穿透),不如visibility干净 - 动画过渡要写全:
transition: visibility 0.2s, opacity 0.2s,不然visibility切换无缓动
移动端骨架屏的坑:iOS Safari不支持background-clip: text动画
有些设计稿要求文字骨架带渐变流动效果,开发者会想到用background-clip: text + color: transparent。但iOS 15.4以下Safari根本不支持该属性动画,结果就是文字一直透明,啥也看不到。
真机测试比看文档靠谱。替代方案其实更稳:用span包每段文字,每个span单独设背景动画,靠定位叠上去。
- 检测是否支持:
CSS.supports('background-clip', 'text'),不支持就fallback到块级骨架 - 不要依赖
will-change: background-position强行提GPU——老iOS反而卡顿 - 字体加载期间(
font-display: optional)可能造成骨架宽高抖动,建议骨架用系统字体,避免等待自定义字体
骨架屏最麻烦的从来不是怎么画出来,而是判断“什么时候该消失”——这个时机一旦错,所有样式努力都白搭。











