图片加载完成后再淡入,需用JS监听load/error事件添加loaded类触发CSS过渡,避免空白闪烁;配合IntersectionObserver实现懒加载,并设置宽高或aspect-ratio防布局抖动。

让图片在加载完成时淡入,关键不是“一加载就动”,而是等图片资源真正就绪后再触发透明度变化。直接给 <img> 加 opacity: 0 再切 opacity: 1,如果没等图片加载完,就会先淡入一个空白框或默认占位符——这反而更影响体验。
用 CSS + JS 监听 load 事件最稳妥
这是兼容性好、逻辑清晰的主流做法:
- HTML 中给图片加一个标识类,比如
<img src="photo.jpg" class="fade-on-load"> - CSS 定义初始隐藏和过渡:
.fade-on-load { opacity: 0; transition: opacity 0.4s ease-out; }
.fade-on-load.loaded { opacity: 1; } - JS 监听
load(成功)和error(失败)两个事件,确保无论是否加载成功都淡入,避免卡死:
document.querySelectorAll('.fade-on-load').forEach(img => {
img.addEventListener('load', () => img.classList.add('loaded'));
img.addEventListener('error', () => img.classList.add('loaded'));
});
避免常见错误
这些细节不注意,淡入就容易失效或闪烁:
- 别在
DOMContentLoaded时就加loaded类——此时图片可能还没下载完 - 别用
display: none初始隐藏图片,否则会破坏文档流,导致淡入时位置跳动 - transition 必须写在初始类(如
.fade-on-load)里,不能只写在.loaded里;否则首次动画不会发生 - 如果页面有大量图片,建议复用同一 observer 或事件监听器,不要为每张图单独新建
进阶:滚动到视口再淡入(懒加载式)
适合长页面中图片较多的场景,节省初始流量并提升首屏速度:
立即学习“前端免费学习笔记(深入)”;
- 用
IntersectionObserver替代 scroll 监听,性能更好:
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('loaded');
observer.unobserve(entry.target);
}
});
}, { rootMargin: '0px 0px 100px 0px', threshold: 0.1 }); - 搭配
loading="lazy"属性(现代浏览器原生支持),让浏览器自动延迟加载非视口内图片 - 注意:仍要保留
load/error监听作为兜底,因为IntersectionObserver不保证图片一定已加载
补充:防字体/布局抖动
即使图片淡入了,如果文字区域因 Web 字体未加载而重排,也会造成视觉跳动:
- 给图片容器设置固定宽高或
aspect-ratio,防止尺寸浮动 - 自定义字体加上
font-display: swap,让文字先用系统字体显示,字体加载完再无感替换 - 慎用
will-change: opacity,移动端可能引发额外合成层,反而卡顿


















