自适应图片

此 Codelab 是由 Google Developers 培训团队开发的“渐进式 Web 应用开发”培训课程的一部分。如果您按顺序学习本 Codelab,将收获最多的课程价值。

如需了解本课程的完整详情,请参阅开发渐进式 Web 应用概览

简介

本实验向您介绍如何使网页图片在所有设备上都能完美呈现。

学习内容

  • 如何使图片具有自适应能力,使其能够针对多种设备类型确定合适的尺寸
  • 如何使用 srcsetsizes 显示适合视口宽度的图片
  • 如何将 picturesource 与媒体查询结合使用,使页面上的图片在窗口调整尺寸时自动响应

注意事项

  • 基本 HTML 和 CSS

所需条件

  • 文本编辑器
  • 可连接终端/shell 的计算机

从 GitHub 下载或克隆 pwa-training-labs 代码库,并安装 Node.js 的 LTS 版本(如果需要)。

如果您没有首选的本地开发服务器,请安装 Node.js http-server 软件包:

npm install http-server -g

转到 responsive-images-lab/app/ 目录并启动服务器:

cd responsive-images-lab/app
http-server -p 8080 -a localhost -c 0

您可以随时使用 Ctrl-c 终止服务器。

打开浏览器并导航到 localhost:8080/

注意:请取消注册任何 Service Worker 并清除 localhost 的所有 Service Worker 缓存,以免它们干扰实验室。在 Chrome DevTools 中,您可以点击 Application 标签页的 Clear storage 部分中的清除网站数据来执行此操作。

如果您有用于打开项目的文本编辑器,请打开 responsive-images-lab/app/ 文件夹。这样可以更轻松地让一切井井有条。否则,请在计算机的文件系统中打开文件夹。您将在其中构建实验的 app/ 文件夹。

此文件夹包含:

  • images 文件夹包含示例图片,每个图片包含多个不同分辨率的版本
  • index.html 是我们的示例网站/应用的主 HTML 页面
  • styles/main.css 是示例网站的级联样式表

在将图片设为自适应图片之前,请确保它们不会溢出屏幕。

styles/main.css 中的 TODO 2 替换为以下代码:

img {
  max-width: 100%;
}

保存代码并在浏览器中刷新页面。请尝试调整窗口大小。图片宽度应完全位于窗口内。

说明

max-width 中的值表示包含元素的百分比,在本例中为 article 元素。

注意:您也可以使用 vw 单位(例如 100vw)根据视口宽度指定 max-width。在这种情况下,我们使用百分比值来使图片与文本保持宽度相同。

我们的目标是让浏览器提取尺寸最小但仍大于图片的最终显示尺寸的图片版本。srcset 可让系统以不同的分辨率列出一组图片,供浏览器在获取图片时从中进行选择。选择哪种浏览器取决于视口尺寸、图片相对于视口的尺寸、用户设备的像素密度以及源文件的尺寸。

向图片添加 srcset

如需在 index.html 中完成 TODO 3.1,请将以下 srcset 属性添加到包含 SFO 映像的 img 元素:

srcset="images/sfo-1600_large.jpg, images/sfo-1000_large.jpg, images/sfo-800_medium.jpg, images/sfo-500_small.jpg"

保存代码并在浏览器中刷新页面。打开浏览器的开发者工具,查看网络请求。请尝试以不同的窗口大小刷新页面。无论窗口大小如何,您应该会看到浏览器正在提取 images/sfo-1600_large.jpg

说明

images/ 文件夹中有 SFO 映像的多个版本,每个版本具有不同的分辨率。我们在 srcset 属性中列出这些属性,以便浏览器可以选择要使用的文件。但是,浏览器无法在加载文件之前确定文件大小,因此始终会选择列表中的第一张图片。

向 srcset 添加宽度描述符

要根据视口宽度加载正确的图片大小,我们需要在浏览器提取文件之前将其告知文件的大小。

如需在 index.html 中完成 TODO 3.2,请向 SFO img 元素添加宽度描述符:

srcset="images/sfo-1600_large.jpg 1600w, images/sfo-1000_large.jpg 1000w, images/sfo-800_medium.jpg 800w, images/sfo-500_small.jpg 500w"

保存代码并在浏览器中刷新页面。请以不同的窗口大小刷新页面,并检查网络请求,了解在每种尺寸下提取的图片版本。在 1x 显示屏上,当窗口宽度小于 500px 时,浏览器会提取 sfo-500_small.jpg;当窗口宽度小于 800px 时,浏览器会提取 sfo-800_medium.jpg,依此类推。

注意:如果浏览器 (HTTP) 缓存中提供了更大的图片版本,那么即使该图片不是由 srcset 指定的图片,它也可能会加载该图片(因为如果浏览器已经在本地存储了分辨率更高的图片,为什么不使用该图片呢?)。为便于在实验中停用此功能,请确保在开发者工具中停用 HTTP 缓存。

注意:在 Chrome 中打开开发者工具后,当窗口调整大小时,系统会显示窗口尺寸(见下图)。在整个 Codelab 中,此功能将非常有用。

chrome-dimensions.png

说明

通过向 srcset 中的每个文件添加宽度描述符,我们可以在提取图片之前告诉浏览器每张图片的宽度(以像素为单位)。然后,浏览器可以使用这些宽度,根据窗口大小确定要获取的图片。它会提取宽度小于视口宽度且宽度最小的图片。

注意:您也可以选择指定像素密度,而不是宽度。不过,您不能在同一个 srcset 属性中同时指定像素密度和宽度。我们将在后面的部分中介绍如何使用像素密度。

以视口宽度的一半显示图像 (50vw)

styles/main.css 中的 TODO 4.1 替换为以下代码:

img#sfo {
  transition: width 0.5s;
  max-width: 50vw;
}

保存代码并在浏览器中刷新页面。尝试在不同窗口大小下刷新网页,并检查每种大小的网络请求。浏览器提取了与之前一样大小的图片。

说明

由于 CSS 会在 HTML 之后解析,因此浏览器无法知道图片在提取时的最终显示尺寸。除非我们另有说明,否则浏览器会假定图片将以 100% 的视口宽度显示,并据此提取图片。我们需要预先告知浏览器图片将以不同尺寸显示。

向图片添加尺寸属性

我们可以为 img 提供一个 sizes 属性,该属性会在浏览器提取图像之前将其告知显示大小。

如需在 index.html 中完成 TODO 4.2,请将 sizes="50vw" 添加到 img 元素中,如下所示:

<img id="sfo" src="images/sfo-500_small.jpg" srcset="images/sfo-1600_large.jpg 1600w, images/sfo-1000_large.jpg 1000w, images/sfo-800_medium.jpg 800w, images/sfo-500_small.jpg 500w" sizes="50vw" alt="View from aircraft window near San Francisco airport">

保存代码并在浏览器中刷新页面。请以不同的窗口大小刷新页面,并随时检查网络请求。您应该会看到,对于您在上一步中测试的大致窗口大小,浏览器提取的图片尺寸较小。

说明

sizes 值与 CSS 中的图片 max-width 值一致。浏览器现在具备了选择正确的映像版本所需的所有信息。浏览器知道自己的视口宽度和用户设备的像素密度,因此为它提供了源文件尺寸(使用宽度描述符)和相对于视口的图片大小(使用 sizes 属性)。

更多信息

向 CSS 添加媒体查询

我们可以使用媒体查询,根据视口宽度实时调整图片大小。

styles/main.css 中的 TODO 5.1 替换为以下代码:

@media screen and (max-width: 700px) {
  img#sfo {
    max-width: 90vw;
    width: 90vw;
  }
}

保存代码并在浏览器中刷新页面。将窗口缩小到小于 700 像素(在 Chrome 中,如果 DevTools 已打开,则屏幕上会显示视口尺寸)。图片应调整为填满窗口宽度的 90%。

说明

媒体查询会测试屏幕的视口宽度,并在视口宽度小于 700 像素时应用 CSS。

更多信息

将媒体查询添加到尺寸属性

我们可以让浏览器了解 sizes 属性中的媒体查询,以便在图片大小改变时获取正确的图片。

如需在 index.html 中完成 TODO 5.2,请更新 SFO 映像中的 sizes 属性:

sizes="(max-width: 700px) 90vw, 50vw"

保存代码并在浏览器中刷新页面。调整浏览器窗口的大小,使其宽度为 600 像素。在 1x 显示屏上,浏览器应提取 sfo-800_medium.jpg

我们可以将 picture 元素和 source 元素与媒体查询结合使用,以在窗口调整大小时更改图片来源。

index.html 中的 TODO 6 替换为以下代码:

<figure>
    <picture>
    <source media="(min-width: 750px)"
            srcset="images/horses-1600_large_2x.jpg 2x,
                    images/horses-800_large_1x.jpg" />
    <source media="(min-width: 500px)"
            srcset="images/horses_medium.jpg" />
    <img src="images/horses_small.jpg" alt="Horses in Hawaii">
    </picture>
    <figcaption>Horses in Hawaii</figcaption>
</figure>

保存代码并在浏览器中刷新页面。请尝试调整浏览器窗口的大小。您应该会在 750 像素和 500 像素看到图片变化。

说明

借助 picture 元素,我们可以使用 source 标记定义多个源文件。这与简单地使用具有 srcset 属性的 img 标记不同,因为通过来源标记,我们可以将媒体查询等内容添加到每一组来源中。我们可以指定在每种窗口大小下使用的图片,而不是为浏览器提供图片大小并让其决定使用哪些文件。

我们提供了一些示例图片,每个版本都采用不同的分辨率并经过剪裁,以较小的尺寸显示图片的焦点。在以上代码中,当大于 750 像素时,浏览器会提取 horses-1600_large_2x.jpg(如果设备使用的是 2 倍的显示屏)或 horses-800_large_1x.jpg。如果窗口宽度小于 750 像素但大于 500 像素,浏览器会提取 horses_medium.jpg。在不到 500 像素的范围内,浏览器会提取后备图片 horses_small.jpg

注意:如果用户的浏览器不支持 picture 元素,它会获取 img 元素中的任何内容。picture 元素仅用于为其包含的 img 元素指定多个来源。img 元素用于显示图片。

更多信息

您已经学习了如何使网页上的图片在所有设备上看起来都美观!

资源

了解如何自动执行此流程

详细了解 srcset 和 size

详细了解艺术指导

如需查看 PWA 培训课程中的所有 Codelab,请参阅课程的欢迎 Codelab