图片懒加载时,如何让加载状态延迟显示更自然?

♫建利 阅读 28

我在给图片列表加懒加载功能时遇到了问题,用loading="lazy"加上loading属性后,加载中的骨架屏总是在图片出现前0.5秒就消失了,看起来很突兀。我试过给骨架屏加固定延迟:


document.querySelectorAll('.image-item').forEach(item => {
  item.querySelector('img').addEventListener('load', () => {
    setTimeout(() => item.classList.remove('is-loading'), 800)
  })
})

但发现网络好的时候图片加载更快,导致延迟时间反而更长。如果网速慢,骨架屏又会在图片出现前就消失。有没有更动态的办法让加载状态在图片真正准备好后再消失?

我来解答 赞 6 收藏
二维码
手机扫码查看
1 条解答
IT人诗晴
我的做法是监听图片的加载状态,同时结合自然的过渡效果来处理。你可以用 IntersectionObserver 来动态检测图片是否进入视口,然后再根据图片的实际加载情况来控制骨架屏的显示和隐藏。

具体来说,先给每个图片元素设置一个默认的加载状态样式,比如骨架屏。然后通过 IntersectionObserver 检测图片是否可见,当图片进入视口时,再绑定 load 事件监听器,确保图片完全加载完成后再移除骨架屏。

代码可以这样写:

document.querySelectorAll('.image-item img').forEach(img => {
let item = img.closest('.image-item');

// 使用 IntersectionObserver 检测图片是否进入视口
let observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
// 图片进入视口后绑定 load 事件
img.addEventListener('load', () => {
// 图片加载完成后移除骨架屏
item.classList.remove('is-loading');
});

// 如果图片已经缓存,直接移除骨架屏
if (img.complete) {
item.classList.remove('is-loading');
}

// 停止观察该图片
observer.unobserve(img);
}
});
}, { threshold: 0.1 }); // 当图片 10% 进入视口时触发

// 开始观察图片
observer.observe(img);
});


这个方法的好处是它不会固定延迟时间,而是根据图片的实际加载状态动态调整。如果图片加载得快,骨架屏会迅速消失;如果加载慢,骨架屏会一直保留到图片加载完成。另外,记得给 .is-loading 状态加一点 CSS 过渡效果,比如淡出动画,这样视觉体验会更自然。

对了,如果你发现某些图片在缓存情况下瞬间加载完成,也可以在代码里加上 img.complete 的判断,避免骨架屏闪一下就消失的情况。

希望这个方案能帮到你!
点赞
2026-02-16 07:01