首屏 Loading 占位怎么避免布局抖动?
我在做首页优化,数据还没回来时用骨架屏占位,但接口一返回,内容高度变了,页面就“跳”了一下,特别难受。
试过给容器写死高度,但不同设备内容长度不一样,写死根本不现实。有没有更灵活的方案?
现在骨架屏是这样写的:
<div class="skeleton-card">
<div class="skeleton-line" style="width: 80%"></div>
<div class="skeleton-line" style="width: 60%"></div>
</div>
而真实内容是动态渲染的列表,每项高度不固定。难道只能靠 JS 提前算高度?感觉好重啊……
几个实用方案:
1. 骨架屏结构和真实列表对齐
你的骨架屏是一个独立的组件,但真实列表是动态渲染的列表项。最简单的办法是让骨架屏的 DOM 结构和真实列表一致,比如真实列表是 ul > li > 内容,那骨架屏也这样写:
这样切换时只是文本节点替换,高度基本不变。
2. 给容器加 min-height
如果你知道列表至少会有几项,比如最少3项,给容器设置一个合理的 min-height,数据先回来的时候不会抖动,只有超过最小高度时才会扩展,这个体验一般能接受。
3. 图片元素用 aspect-ratio
如果列表里有图片,提前占好坑:
图片加载前就有高度了,不会因为图片加载再跳一下。
4. 控制占位项数量
如果列表最多显示 10 条,骨架屏就渲染 10 个占位项,数量对上了高度差异会小很多。
最省事的组合方案:骨架屏 DOM 结构对齐真实列表 + 列表容器 min-height + 图片 aspect-ratio。基本上就能解决大部分抖动问题了,不用写复杂的 JS 提前算高度。
给骨架屏的容器加上这两个属性:
真实内容加载后,这个容器会自然撑开到内容高度,不会出现跳变。如果内容很短,至少保持200px高度;如果内容很长,就按实际高度显示。
还有个优化点:给动态内容加个过渡动画
这样就算高度变化也会有个平滑过渡,不会那么突兀。我之前在移动端项目用这招,效果不错。
实在不行的话,还有个土办法:给每个列表项单独设置骨架屏,用flex布局撑开高度。但CSS方案能解决的话就别折腾JS了,性能更好。