图片懒加载时占位图怎么保持宽高比不塌陷?
我用 Intersection Observer 做了图片懒加载,但发现图片还没加载出来时,因为没有设置宽高,页面会先塌陷一下,然后图片加载完又撑开,体验很不好。我试过给 img 加 width 和 height,但响应式布局下固定像素值不合适。
看到有人说用 padding-top 百分比来维持比例,但我加了之后发现图片加载出来位置不对,或者容器高度异常。下面是我目前的占位样式:
.lazy-image {
width: 100%;
height: 0;
padding-top: 75%; /* 4:3 比例 */
background: #f0f0f0;
position: relative;
}
.lazy-image img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
}
这样写在懒加载时确实不会塌陷了,但有时候图片加载后显示不全,或者和周围元素间距错乱,是不是哪里没处理对?
一是直接上
aspect-ratio,现在浏览器支持度够用了:二是坚持用 padding-top 方案的话,给 img 加上
display: block就对了,之前显示不全大概率就是这行漏了导致的。首先,你的 padding-top 方法思路是对的,但有个关键点没处理好:图片加载完成后,占位容器的样式没有正确切换。
核心问题在于,当 img 标签用 lazy load 时,它的 src 是空的或者用 data-src,图片还没加载时浏览器不知道尺寸。padding-top 方案是用内边距来"欺骗"浏览器预留空间,这个思路没问题。但你的代码里,图片加载后还是维持原来的 padding-top 样式,这时候就会出问题——因为 img 已经是绝对定位贴在整个容器上了,而容器高度是 padding 撑起来的,图片内容可能和容器实际高度不匹配。
正确的做法是:图片加载完成后,需要调整或移除占位样式。
我来给你一个完整可用的方案:
CSS 部分:
JavaScript 部分(Intersection Observer):
HTML 结构:
为什么你之前会出问题?
你原来的代码里,图片加载后还是维持着 padding-top: 75%,这时候如果真实图片比例不是 4:3(比如是 16:9 或者 1:1),就会出现显示不全或者错位。因为容器高度是由 padding 决定的,不是由图片实际尺寸决定的。
我上面给的方案里,图片加载完成后通过 JS 给容器加 loaded 类,这时候可以:
1. 把 padding-top 设为 0,让高度由图片自然决定
2. 或者保持 padding-top 但确保图片比例一致
更现代的方案:aspect-ratio
如果你的项目不需要支持太老的浏览器,可以直接用 CSS 的 aspect-ratio 属性,更简洁:
这个方案不需要 padding-top,浏览器会自动保持比例,而且图片加载后会自然替换容器高度。兼容性方面,现代浏览器都支持了(Chrome 88+, Firefox 108+, Safari 15+),如果需要兼容更老的浏览器就用 padding-top 方案。
你根据项目情况选一个就行。