响应式图像以获得更好的性能:开始使用 srcset 和 picture
大家好,今天的文章将探讨响应式图像、屏幕尺寸、像素密度,以及这些属性如何srcset
帮助sizes
我们实现更佳的性能和绝佳的用户体验。请阅读到最后,您将获得一份惊喜。
实现响应式图像并不复杂。然而,它需要我们编写更多代码,并且由于图像大小必须直接在<img>
浏览器标签中声明,因此也迫使我们将 CSS 和 HTML 耦合在一起。
测试响应式图像也需要新的方法,因为我们现在需要确保在正确的时间加载正确的分辨率。
和属性srcset
sizes
响应式图像规范可以归结为两个标签和两个属性。我们要看的第一个标签是我们之前提到的<img>
标签。该标签新增了两个属性<img>
:srcset
和sizes
。这两个属性告诉浏览器,给定图像可用的分辨率以及在任意给定断点处图像应显示的尺寸。基于这些信息,浏览器能够为任何给定设备选择并下载最优的图像文件。
让我们首先看一下srcset
属性。
属性srcset
<img srcset="/assets/images/image-tiny.jpeg 150w,
/assets/images/image-small.jpeg 300w,
/assets/images/image-medium.jpeg 600w,
/assets/images/image-large.jpeg 1000w,
/assets/images/image-extra-large.jpeg 1500w"
src="/assets/images/image-medium.jpeg"
alt="Banner image">
该srcset
属性包含一个以逗号分隔的 URL 列表,其中包含 w 描述符,用于告知浏览器每个源图像的宽度。
这种语法的一大优点是,我们无需告诉浏览器针对不同的像素密度显示器使用哪些图像,以及针对不同的屏幕尺寸使用哪些图像。浏览器可以自行选择最佳图像尺寸。
请注意,此scr
属性是针对不支持该属性的浏览器srcset
(例如 IE 😒)的后备选项。
在上面的代码片段中,srcset
我们通过该属性提供了五种不同尺寸的图像源:150px、300px、600px、1000px 和 1500px。浏览器会根据屏幕尺寸和像素密度选择最佳图像。请观看下面的视频:
如果我们打开网络选项卡,我们会看到图像是在需要时获取的:
这样可以获得更好的性能,因为图像可以在较小的设备上快速加载,从而带来更好的用户体验。
在上面的例子中,图片宽度为 100vw,如果我们有一个布局,其中图片宽度在桌面上为 50vw(减去一些 padding),在移动设备上为 100vw(减去一些 padding),会怎么样?
这就是sizes
目的所在。
属性sizes
虽然该srcset
属性描述的是源文件的实际宽度,但它sizes
告诉浏览器图片在屏幕上的显示宽度。这是通过使用内联媒体查询来实现的。它们的工作原理与 CSS 中的完全相同(没有花括号),只是你只能用它来描述图片的显示宽度。让我们来看看:
<img srcset="/assets/images/image-tiny.jpeg 150w,
/assets/images/image-small.jpeg 300w,
/assets/images/image-medium.jpeg 600w,
/assets/images/image-large.jpeg 1000w,
/assets/images/image-extra-large.jpeg 1500w"
sizes="(max-width: 700px) calc(100vw - 10px),
calc(50vw - 10px)"
src="/assets/images/image-medium.jpeg"
alt="A photo of Lyon city">
在(属性的)第一行,sizes
我们指定了屏幕宽度小于 时图像的宽度700px
。然后,在第二行,我们指定了默认宽度(在本例中,指的是屏幕尺寸大于 的设备700px
)。
这样,浏览器就能知道布局中图片的宽度,并决定加载哪个文件。看看结果:
请注意,属性中图片 URL 的顺序
srcset
无关紧要。sizes
然而,属性中的顺序却非常重要!浏览器将使用第一个与浏览器当前状态匹配的媒体查询。
这很神奇,但还有更多。现在假设我们想在用户喜欢深色主题的情况下使用其他图片。
为此,我们可以使用<picture>
标签。让我们深入探讨一下。
图片
您可以将<picture>
元素视为一组图像源。每个元素的<source>
工作方式与单个<img>
标签类似,但添加了 media 属性。这使我们能够为不同的媒体查询指定不同的源组,同时仍然受益于浏览器为给定图像选择最佳分辨率的能力。
让我们使用它来指定两个源,一个用于浅色主题,一个用于深色主题:
<picture>
<!-- Dark theme -->
<source media="(prefers-color-scheme: dark)"
srcset="/assets/images/tiny-dark.png 150w,
/assets/images/small-dark.png 300w,
/assets/images/medium-dark.png 600w,
/assets/images/large-dark.png 1000w,
/assets/images/xl-dark.png 1500w"
sizes="(max-width: 700px) 100vw, 50vw">
<!-- Light theme -->
<source srcset="/assets/images/tiny.png 150w,
/assets/images/small.png 300w,
/assets/images/medium.png 600w,
/assets/images/large.png 1000w,
/assets/images/xl.png 1500w"
sizes="(max-width: 700px) 100vw, 50vw">
<img src="/assets/images/medium.png" alt="Banner image">
</picture>
在浏览器中看起来是这样的:
要模拟暗模式:
command
++shift
然后p
粘贴“prefers-color-scheme”并选择亮色或暗色。
请注意,picture 元素本身不显示任何内容,它为其包含的<img>
元素提供了一个上下文,使其能够从多个 URL 中进行选择。这意味着您应该始终<img>
在标签内添加一个标签<picture>
来指定alt
属性,并loading="lazy"
指定是否要延迟加载图像。
奖金
可以使用更优的图像编码(例如 webP 和 AVIF)来获得更佳的性能。更多详情(回退、浏览器支持等),请参阅下方主题:
另外,您可以使用这个 npm pkg自动生成多种图像尺寸。
包起来
我们了解了如何使用srcset
标签sizes
和<img>
标签<picture>
。我们还了解了何时使用它们以及为什么使用它们。既然我们了解了这些功能有多么实用,那就没理由再强迫人们在手机上使用 3G 或 4G 网络连接加载不必要的大图片了 :)
这篇文章就到这里。希望你喜欢。如果喜欢,请分享给你的朋友和同事,并在 Twitter 上关注我@theAngularGuy,我会在这里发布关于 Web 开发和计算机科学的推文。
祝你今天过得愉快!