在用户界面中使用图片和动画已成为现代 Web 应用程序中的常见情况。尽管这些现代设计都致力于改善应用程序的用户体验,但如果这些图像在所有设备上都没有良好的响应,事情就会适得其反。
作为开发人员,我们必须满足所有这些要求。但大多数时候,由于我们正在寻求更高级别的解决方案,因此会忽略一些可能会带来巨大影响的小事。
在 picture
标签和 img
标签之间做选择可能是一个很小的决策,但如果你做出了正确的选择,就能改善用户体验和性能。
本文将讨论 picture 和 img 标签之间的区别,以及 picture
标签比 img
标签更好用的原因所在。
下次当你创建一个 React 图像组件时,请一定要在其中实现你即将在本文中学习的最佳实践。根据接收到的 props
返回正确的标签,并处理好所有必要的回退。你甚至可以在 Bit.dev 的组件中心上共享它,这样你的团队和你自己将来都能重用它。这样,你就会拥有一个优化极佳的图像组件,可以毫不犹豫地用在所有 Web 项目中。
img
标签面临的问题
众所周知,很长一段时间以来,img
标签一直是 HTML 的核心元素之一,它的简单性和可用性是毋庸置疑的。
然而,随着各种屏幕尺寸、分辨率的设备和复杂用户需求的发展,img
标签的响应性和在多设备应用中使用的能力开始受到质疑。
所有这些问题可以归结为两大方面:
- 分辨率切换:为小屏幕设备提供较小尺寸图像的问题。
- 图像切换:在不同屏幕上显示不同图像的问题。
现在,我们来看看如何解决这些问题,以及 picture
标签的其他特性。
使用 srcset
和 size
属性切换分辨率
如前所述,当今的网页设计师经常使用高分辨率图像来增加用户吸引力。但是作为开发人员,我们必须非常小心地选择正确的 HTML 元素。
假设你对高分辨率图像使用简单的 img
标签。在这种情况下,运行你应用程序的每台设备都会使用相同的图像,并且肯定会导致屏幕分辨率较低的设备(如移动设备)出现性能问题。
这可能会导致更长的图像加载时间以及从上到下一块一块地图像加载。
通过使用 srcset
和 size
属性,可以使用 picture
图片标签轻松解决这一问题。
<picture>
<source
srcset="small-car-image.jpg 400w,
medium-car-image.jpg 800w,
large-car-image.jpg 1200w"
sizes="(min-width: 1280px) 1200px,
(min-width: 768px) 400px,
100vw">
<img src="medium-car-image.jpg" alt="Car">
</picture>
其中:
srcset
属性接收多个图像,其宽度都以像素为单位,浏览器使用这些值在提供的图像之间进行选择。在上面的示例中,同一图像有 3 个版本,具有 3 种不同的尺寸。sizes
属性定义图像将在屏幕上占据的空间。在上面的示例中,如果屏幕的最小宽度为 1280px,则图像将占据 1200px。
话虽如此,建议不要仅将 picture
标签用于分辨率切换,因为可以使用更新版本的 img
标签(具有更多的浏览器支持)来实现此目的。如下面这段代码所示:
<img srcset="small-car-image.jpg 400w,
medium-car-image.jpg 800w,
large-car-image.jpg 1200w"
sizes="(min-width: 1280px) 1200px,
(min-width: 768px) 400px,
100vw"
src="medium-car-image.jpg" alt="Car">
但在大多数情况下,我们需要同时处理分辨率切换和图像切换的问题,并且 picture
标签仍然是最好的解决方案。
接下来,让我们看看如何使用 picture
标签解决图像切换问题。
使用媒体属性切换图像
图像切换背后的主要思想是根据设备的屏幕尺寸显示不同的图像。在大多数情况下,切换到移动设备时,在大屏幕上看起来很棒的图像可能会被裁剪或显得很小。
我们可以为不同的屏幕尺寸提供不同版本的图像来解决这一问题。这些不同的版本可以是同一图像的横向,纵向或任何自定义版本。
我们可以使用 picture
标签中的多个 source
子标签轻松实现分辨率切换。
<picture>
<source ....>
<source ....>
<source ....>
</picture>
然后,我们可以使用 media
属性定义使用这些源的不同媒体条件。我们还可以按照上一节中讨论的类似方式使用 srcset
和 size
属性。以下示例显示了使用 picture
标签解决图像切换和分辨率切换的完整示例。
<picture>
<source media="(orientation: landscape)"
srcset="land-small-car-image.jpg 200w,
land-medium-car-image.jpg 600w,
land-large-car-image.jpg 1000w"
sizes="(min-width: 700px) 500px,
(min-width: 600px) 400px,
100vw">
<source media="(orientation: portrait)"
srcset="port-small-car-image.jpg 700w,
port-medium-car-image.jpg 1200w,
port-large-car-image.jpg 1600w"
sizes="(min-width: 768px) 700px,
(min-width: 1024px) 600px,
500px">
<img src="land-medium-car-image.jpg" alt="Car">
</picture>
如果屏幕方向是横向,则浏览器将显示第一组图像;如果屏幕方向是纵向,则浏览器将使用第二组图像。除此之外,你还可以将 media
属性与 max-width
和 min-width
参数一起使用:
<picture>
<source media="(max-width: 767px)" ....>
<source media="(min-width: 768px)" ....>
</picture>
说明:
picture
标签中最后一个img
标签用于向后兼容不支持picture
标签的浏览器。
用于受部分支持的图像类型
随着技术的飞速发展,新的图像格式也在不断涌现。其中一些格式(例如 webp、svg 和 avif)提供了更好的用户体验。
另一方面,某些浏览器对这些现代图像类型存在限制,如果我们不使用兼容的图像类型,事情将会适得其反(本站提供了图片格式转换工具,当浏览器不支持较新的图片时,可以考虑使用该工具把图片转换成受浏览器支持的格式)。
但是,我们可以使用 picture
标签轻松解决这个问题,因为它允许我们在其中包含多个来源。
<picture>
<source srcset="test.avif" type="image/avif">
<source srcset="test.webp" type="image/webp">
<img src="test.png" alt="test image">
</picture>
上面的示例包括 avif、webp 和 png 格式的三种图像类型。首先,浏览器将尝试 avif 格式;如果失败,则将尝试 webp 格式。如果浏览器不支持这两种方式,它将使用 png 图像。
Chrome 宣布“DevTools 将在 Rendering 选项卡中提供两个新的仿真,以模拟部分受支持的图像类型”后,picture
标签用起来就更有意思了。
从 Chrome 88 开始,你可以使用 Chrome DevTools 检查浏览器与图像类型的兼容性。
总结
本文我们讨论了为什么 picture
标签比 img
标签更好用的原因,但有一点必须指出,那就是 img
标签并没有消亡,或者说不会很快消亡。如果我们能明智地使用 img
提供的属性,如 srcset
和 size
,则可以从中获得最大收益。例如,我们可以只使用 img 标签来解决“分辨率切换”问题。
另一方面,我们可以使用 picture
标签的媒体查询和其他属性轻松实现分辨率切换和图像切换。用于部分受支持的图像类型和 Chrome DevTools 的支持可以被认为是 picture
标签的额外优势。
综上所述,这两种元素各有利弊。因此,我们必须根据我们的需求仔细考虑和使用最合适的元素。
全文完,感谢阅读,希望对你在使用图片的过程中带来一定的帮助。