为每个设备提供合适大小的图像是您能做的最高影响力的性能优化之一。在 375px 手机屏幕上 显示 3000px 的英雄图像会浪费带宽并降低 LCP。srcset 和 sizes 属性通过原生 HTML 解决这个问题——无需 JavaScript。
问题:所有设备使用同一张图像
没有响应式图像,通常是提供最大的图像并让 CSS 缩小它。这在视觉上可行,但浪费带宽: 即使小屏幕上 60KB 的版本看起来完全相同,400KB 的桌面图像在移动端也要花费同样多。
srcset:定义图像变体
srcset 属性列出可用的图像文件及其宽度:
<img
src="hero-800.webp"
srcset="hero-400.webp 400w,
hero-800.webp 800w,
hero-1600.webp 1600w"
alt="英雄图像"
/>
浏览器读取描述符(400w = 400像素宽)和当前视口宽度来选择最佳文件。 没有 sizes 属性,它假设图像将是 100vw 宽——通常是错误的。
sizes:告知浏览器显示宽度
sizes 属性描述图像在不同视口断点下的显示宽度:
<img
srcset="hero-400.webp 400w, hero-800.webp 800w, hero-1600.webp 1600w"
sizes="(max-width: 640px) 100vw,
(max-width: 1024px) 50vw,
800px"
alt="英雄图像"
/>
这告诉浏览器:在移动端(<640px)图像是全宽;在平板上是视口的 50%; 在桌面上始终是 800px。浏览器结合设备像素比来选择最佳文件。
设备像素比
视网膜屏幕的设备像素比(DPR)为 2 或 3,意味着需要 2–3 倍更多的像素才能清晰渲染。 使用 sizes="100vw" 的 375px 视网膜屏幕浏览器实际上会请求 800w 图像 (375 × 2 DPR ≈ 750px → 最近的变体是 800w)。提供足够的变体时会自动处理。
picture 元素:艺术指导
对于想在移动端提供完全不同裁剪(而不仅仅是更小)的情况,使用 <picture>:
<picture>
<source media="(max-width: 640px)" srcset="hero-square-400.webp" />
<source media="(min-width: 641px)" srcset="hero-wide-1600.webp" />
<img src="hero-wide-1600.webp" alt="英雄图像" />
</picture>
使用 picture 提供现代格式
使用 <picture> 向支持的浏览器提供 AVIF,以 WebP 和 JPEG 作为回退:
<picture>
<source type="image/avif" srcset="hero.avif" />
<source type="image/webp" srcset="hero.webp" />
<img src="hero.jpg" alt="英雄图像" />
</picture>
Next.js:自动生成 srcset
Next.js 的 <Image> 组件根据 deviceSizes 和 imageSizes 配置自动生成 srcset。sizes 属性 直接映射到 HTML sizes 属性:
<Image
src="/hero.jpg"
width={1600}
height={900}
sizes="(max-width: 640px) 100vw, 800px"
alt="英雄"
/>
没有 sizes 属性,Next.js 默认为 100vw——正确设置以避免 加载不必要的大图像。完整的权衡分析请参阅 next/image 指南。
快速清单
- 始终设置
sizes——不要依赖100vw默认值 - 每张图像提供至少 3 个宽度变体(小、中、大)
- 包含用于视网膜支持的 2× 变体
- 用
loading="lazy"懒加载折叠以下的图像 - 用
<link rel='preload'>预加载 LCP 图像
要手动将图像转换为 WebP,请使用 Picovert 的 PNG to WebP 转换器。