可通过CSS过渡+JS监听load/error事件实现图片加载前占位动画,需设固定宽高防塌陷,用opacity过渡而非display:none,并注意lazy loading、decoding异步解码及布局稳定性问题。

图片加载前显示占位动画
HTML5 本身不提供内置的图片加载动画机制,但可以通过 img 元素的 loading 属性配合 CSS 过渡 + JavaScript 监听 load 和 error 事件来实现“等待中显示动画,加载完淡出”的效果。关键不是等 HTML5 “支持动画”,而是控制 DOM 状态与样式切换。
- 必须给
img设置固定宽高或最小尺寸(否则动画容器会塌陷) - 推荐用
opacity+transition实现淡入,避免用display: none—— 否则无法触发load事件 - 初始状态设为
opacity: 0.3并加旋转/脉冲动画,加载成功后移除类名或设opacity: 1
CSS 配合 img 的 loading="lazy" 使用注意事项
启用懒加载后,load 事件可能延迟触发,甚至在用户滚动到视口前不会触发。若你依赖该事件启动动画结束逻辑,就会出现“图片已显示但动画没停”的问题。
-
loading="lazy"在 Safari 早期版本和部分安卓 WebView 中不支持,需降级 fallback(比如默认不 lazy,通过 JS 检测后动态添加) - 不要把动画结束逻辑只绑在
img.onload;建议同时监听img.complete && img.naturalWidth > 0(同步加载完成时) - 对懒加载图片,可配合
IntersectionObserver:进入视口时先加 loading 动画类,再尝试设置src或触发decode()
用 img 的 decoding="async" 影响动画时机吗?
有影响,但常被忽略。decoding="async" 让浏览器异步解码图片,可能造成 load 事件触发后图像仍短暂空白或闪烁——此时如果动画已结束,用户会看到“先闪一下再稳定”的异常。
奥硕企业网站管理系统具有一下特色功能1、双语双模(中英文采用单独模板设计,可制作中英文不同样式的网站)2、在线编辑JS动态菜单支持下拉效果,同时生成中文,英文,静态3个JS菜单3、在线制作并调用FLASH展示动画4、自动生成缩略图,可以自由设置宽高5、图片批量加水印,可以自由设置字体,大小,样式,水印位置(同时支持文字或图片类型水印)6、强大的标签式数据调用,可以调用(新闻,产品,下载,招聘)支持
- 默认值是
"sync",对多数小图够用;大图才考虑"async" - 若启用了
decoding="async",动画收尾不应只依赖load,最好加上img.decode().then(...)确保渲染就绪 - 注意
decode()是 Promise,需处理 rejected 情况(如损坏图片),否则动画卡在 loading 状态
img.addEventListener('load', () => {
img.decode().then(() => {
img.classList.remove('is-loading');
}).catch(() => {
img.classList.add('is-error');
});
});
纯 CSS 方案:用 background-image + @property 做渐进动画
如果你能接受用 div 替代 img 标签(比如响应式背景图场景),CSS 新特性 @property 可以实现更可控的加载过渡,无需 JS。
立即学习“前端免费学习笔记(深入)”;
- 需要声明
@property --loaded并设initial-value: 0,然后用transition驱动 opacity 或 transform - 配合
:has(img:loaded)(目前仅 Safari 16.4+ 支持)可实现自动检测,但兼容性差,生产环境慎用 - 更稳妥的是用 JS 设置自定义属性:
el.style.setProperty('--loaded', '1'),再由 CSS 响应
div {
background-image: url('photo.jpg');
opacity: 0;
transition: opacity 0.3s ease;
}
div[style*="--loaded: 1"] {
opacity: 1;
}
实际中最容易漏掉的是:**没有给图片容器设 min-height 或 aspect-ratio,导致加载前高度塌陷、布局跳动,动画看起来像“突然弹出来”而不是平滑过渡**。










