loading="lazy"不生效的主因是父容器设overflow:hidden或transform导致Intersection Observer失效,且仅对<img>有效、不支持background-image;首屏图禁用,须配宽高防抖动,srcset必须搭配准确sizes和真实w描述符。

图片资源管理不是“塞进去就完事”,而是让浏览器在正确时间、用正确格式、加载正确尺寸的图——做错一步,首屏就多等800ms,布局还会跳。
为什么 loading="lazy" 有时不生效
常见错误是父容器设置了 overflow: hidden 或 transform,导致 Intersection Observer 无法触发;另外,loading="lazy" 对 background-image 完全无效,它只作用于 <img> 标签。
- 非首屏图必须加
loading="lazy",但 banner、logo、首屏轮播图不能加,否则可能白屏或 FOUC - 务必配合固定宽高(推荐用 CSS
aspect-ratio)或占位符,否则加载时会触发回流 - 若需兼容老浏览器,用
IntersectionObserver替代,但别监听scroll——性能差且易抖动
srcset + sizes 配错等于没写
只写 srcset 不配 sizes,浏览器只能按设备像素比瞎猜,大概率下错高清图;而 sizes="100vw" 写死,会让侧边栏里一张小图也拉取 2000px 宽版本。
- 安全写法:
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw",对应实际容器宽度 -
srcset中的400w描述符必须和原图真实宽度一致,否则切换逻辑失效 - 生成多尺寸图时,建议文件名带分辨率标识,如
hero-800w.webp,方便人工核对
WebP/AVIF 怎么 fallback 才不崩
直接用 <picture> 是标准解法,但很多人漏掉最后的 <img> 兜底,或者把 src 错写在 <source> 上——src 只能出现在 <img> 里。
立即学习“前端免费学习笔记(深入)”;
- AVIF 编码慢、iOS 16.4+ 和 Chrome 109+ 才支持,适合静态运营图;WebP 压缩率高、兼容性好,是当前最稳妥升级项
- 千万别用 JS 动态判断格式再插入
<img>——会破坏预加载器(preload scanner),首屏图晚 1~2 个渲染周期 -
<source type="image/avif" srcset="photo.avif">后必须跟<img src="photo.jpg" alt="...">,缺一不可
宽高不声明,布局跳动就躲不掉
没设 width 和 height,浏览器解析到 <img> 时无法预留空间,等图下载完才重排,页面“一抖一抖”就是这么来的。
- 内联
width/height最简单,但响应式场景下推荐 CSSaspect-ratio(现代浏览器全覆盖) - 如果用
object-fit裁剪图片,仍要先设容器宽高,否则裁剪区域无法确定 - 服务端渲染(SSR)页面尤其要注意:服务端吐出的 HTML 必须含宽高信息,否则客户端 hydration 时仍会跳
真正卡顿的根源,往往藏在「写了但没生效」的属性里:比如 loading="lazy" 被 overflow: hidden 截断,或者 decoding="async" 写了却没配 fetchpriority="low"。优化不是堆功能,而是每一步都验证是否真被浏览器执行了。



















