HTML 教程 / 使用 srcset、sizes 和 picture 创建响应式图片

响应式图像为浏览器提供不同分辨率或不同构图的文件,以便选择适合显示的图像。使用 srcset 和 sizes 来选择同一图像的不同分辨率,当屏幕较窄时使用 picture 来选择不同的图像裁剪。

获取示例图像文件

这些示例使用同一张湖泊图片的三种宽度和一个突出显示树木的方形裁剪。下载文件并将其保存在与您的 HTML 文件相同的文件夹中,以测试未更改的相对 URL。根据 使用 img 插入图片:替代文本与尺寸 中的原则准备文件、替代文本和尺寸。

前三个保留了场景和纵横比。方形文件对于窄屏显示有不同的构图。

使用 srcset 和 sizes 选择图像分辨率

描述符 480w、960w 和 1600w 在 srcset 中指明了每个文件的实际像素宽度。sizes 描述了图像在不同窗口条件下的预期设计宽度。

<img class="example-fluid"
  src="html-image-sample-lake-tree-960-v1.webp"
  srcset="html-image-sample-lake-tree-480-v1.webp 480w,
          html-image-sample-lake-tree-960-v1.webp 960w,
          html-image-sample-lake-tree-1600-v1.webp 1600w"
  sizes="(max-width: 800px) 100vw, 800px"
  alt="湖中小岛上的一棵树,背景是群山"
  width="1600" height="900">

这假设图像的宽度大约与显示窗口相同,直到 800 CSS 像素,并且不会超过 800 CSS 像素。如果您的布局不同,请更改 sizes 以适应。src 为不支持 srcset 的环境提供了回退解决方案。

.example-fluid {
  display: block;
  width: 100%;
  max-width: 800px;
  height: auto;
}

此CSS仅适用于具有类example-fluid的第一个示例。浏览器还可以考虑设备的像素密度和缩放。因此,窄视口并不保证会选择480像素文件。sizes描述的是显示的CSS像素,而不是下载文件的宽度。

为固定显示宽度使用密度描述符

如果图像总是以480像素的CSS宽度显示,可以建议1x和2x候选项。不要在此形式下使用sizes。

<img class="example-fixed"
  src="html-image-sample-lake-tree-480-v1.webp"
  srcset="html-image-sample-lake-tree-480-v1.webp 1x,
          html-image-sample-lake-tree-960-v1.webp 2x"
  alt="湖中小岛上的一棵树,背景是群山"
  width="480" height="270">
.example-fixed {
  display: block;
  width: 480px;
  height: auto;
}

第一个示例的 CSS 不适用于此图片。此 CSS 将显示宽度固定为 480 像素,因此图片可能会超出较窄的容器。如果显示宽度需要根据布局变化,请使用前面提到的 w 和 sizes 方法。请不要在单个 srcset 中混合使用 w 和 x 描述符。

使用 picture 更改裁剪

picture 可以提供不同的构图,而不仅仅是不同的分辨率。此示例在窗口宽度不超过 600 像素时使用正方形裁剪,否则使用横向图片。

<picture class="example-picture">
  <source media="(max-width: 600px)"
          srcset="html-image-sample-lake-tree-square-800-v1.webp"
          width="800" height="800">
  <img src="html-image-sample-lake-tree-960-v1.webp"
       alt="湖中小岛上的一棵树,背景是群山"
       width="960" height="540">
</picture>

选择裁剪和调整其显示宽度是两种不同的操作。将这段 CSS 添加到 head 中的 style 元素或已链接的样式表,使 picture 中的图片适应较窄的父元素,同时保持其比例。

.example-picture img {
  display: block;
  max-width: 100%;
  height: auto;
}

将一张湖泊照片裁剪为正方形,以树为中心

上图显示了在窄屏幕上使用的方形文件;文章本身中的这张照片不会随窗口宽度变化而改变。picture始终需要一个img 元素,并通过 src 提供回退图片、通过 alt 提供替代文本。每个source提供一个条件和一个候选文件;图片的替代文字属于img。

检查浏览器选择了哪张图片

将四个图片文件保存到 index.html 所在目录,同时保留它们的文件名。在 body 中放置一个 HTML 示例,并在 head 中的 style 元素中或在单独的样式表中放置其 CSS。为了测试在移动设备上实际窗口宽度下的效果,将 <meta name="viewport" content="width=device-width, initial-scale=1"> 添加到 head 中。

  1. 在浏览器中打开 index.html,并打开开发者工具的网络面板。
  2. 更改视口的宽度,禁用缓存,并重新加载页面。检查图片请求的文件名,以查看加载了哪些候选文件。
  3. 对于示例 picture,请在浏览器窗口宽度为 600 像素或更少时加载一次,再在大于 600 像素时加载一次。检查在最窄宽度下的正方形裁剪,以及在最宽宽度下的横向文件。

您也可以在控制台中检查这些值。currentSrc 显示浏览器当前选择的图像的 URL。第一个命令针对示例 srcset;第二个命令针对示例 picture。

document.querySelector('.example-fluid').currentSrc
document.querySelector('picture img').currentSrc

即使窗口宽度相同,像素密度和缩放也会决定选择哪个文件 srcset。 如果已经加载了较大的文件,通过缩小窗口不会立即被较小的文件替换。 在比较之前,请更改条件,禁用缓存并重新加载。

检查分辨率的变化和图像裁剪的调整

情况 机制 需要检查的内容
相同构图,自适应宽度 描述符 w + sizes 检查 sizes 是否描述了布局,以及 currentSrc 是否指定了一个建议的候选
相同构图,固定宽度 1x / 2x 密度描述符帮助浏览器选择文件,本身不会使显示宽度随容器变化
随视口变化而使用不同构图 picture + source[media] 将 600px 的方形裁剪与 601px 的横向裁剪进行比较

显示窗口是浏览器用于排列页面的区域。设备的像素密度将 CSS 像素与屏幕的物理像素连接起来。密度、缩放和缓存状态甚至可以在相同窗口宽度下影响分辨率的选择,因此不应为 srcset 承诺固定的文件名。应将图像片段的媒体条件单独测试,而与分辨率更改分开。

如果选择了错误的图像

  • 请检查每个 w 标识符是否与文件的实际像素宽度相对应。
  • 在每种窗口大小下,将 sizes 与 CSS 宽度进行比较。
  • 切换分辨率时,用 srcset、sizes 提供构图相同而像素宽度不同的文件;更换构图时,用 picture 提供不同裁剪的文件。
  • 在 picture 中保留 img 上有意义的 alt。

有关详细的选择规则,请参阅响应式图像指南 MDN 和 HTML 图像规范 WHATWG。