规范性语法

<picture> 元素不会单独渲染任何内容,而是充当内部 <img> 元素的决策引擎。 用于指示要呈现的内容<picture> 遵循 <audio><video> 元素已设置的先例:封装容器元素 包含各个 <source> 元素。

<picture>
   <source …>
   <source …>
    <img …>
</picture …>

该内部 <img> 还为不支持自适应图片的旧版浏览器提供了一种可靠的后备模式: 如果用户浏览器无法识别 <picture> 元素,系统会忽略该元素。然后,<source> 元素也会被舍弃, 因为浏览器根本无法识别这些键,或者如果没有 <video><audio> 父级,浏览器就无法获得有意义的上下文。 不过,任何浏览器都可以识别内部 <img> 元素,并且其 src 中指定的来源将按预期呈现。

“艺术指导”包含 <picture> 的图片

根据网页中图片的大小更改图片的内容或宽高比通常被称为“以艺术为导向”的 自适应图片。srcsetsizes 旨在以隐蔽的方式运行,根据用户的浏览器命令无缝替换源代码。 不过,您有时可能会想跨断点更改来源,以便更好地突出显示内容,就像调整网页布局一样。 例如:中心焦点较小的全宽标题图片可能在较大的视口上效果很好:

一张标题宽度图片,展示了一朵被叶子和茎环绕的长春花,正在被蜜蜂探望。

但在缩小以适应小视口时,图片的中心焦点可能会丢失:

一张已按比例缩小的长春花色标题图片。蜜蜂几乎看不见了。

这些图片来源的正文相同,但为了在视觉上更突出该正文,您需要添加 更改图像来源的比例。例如,将图片中心的放大范围较小;以及 裁剪掉边缘的部分细节:

长春花色的放大图。

这种“剪裁”的方式都可以通过 CSS 实现,但会让用户请求构成该图片的所有数据 即使他们可能永远也不会看到该广告

每个 source 元素都有一些属性,用于定义选择该 source 的条件:media。该属性接受 媒体查询,以及接受媒体类型(以前称为“MIME 类型”)的 type。来源中的前 <source> 选择与用户当前浏览上下文相匹配的内容,以及该 source 上的 srcset 属性的内容 将据此确定适合该情境的合适候选定位设置。在此示例中,第一个具有 media 属性的 source 与用户的视口尺寸相匹配的图片将会是选中的图片:

<picture>
  <source media="(min-width: 1200px)" srcset="wide-crop.jpg">
  <img src="close-crop.jpg" alt="…">
</picture>

如果 source 元素都与其 mediatype 不匹配,则您应始终按顺序指定内部 img 图片将作为“默认”模板来源。如果您使用 min-width 个媒体查询,您希望 如前面的代码所示。使用 max-width 媒体查询时,您应将最小的来源放在最前面。

<picture>
   <source media="(max-width: 400px)" srcset="mid-bp.jpg">
   <source media="(max-width: 800px)" srcset="high-bp.jpg">
   <img src="highest-bp.jpg" alt="…">
</picture>

根据您所指定的条件选择来源后,系统会将 source 上的 srcset 属性传递给 <img>,就像它是在 <img> 本身中所定义的,这意味着您可以随意使用 sizes 优化艺术导向图片 来源。

<picture>
   <source media="(min-width: 800px)" srcset="high-bp-1600.jpg 1600w, high-bp-1000.jpg 1000w">
   <source srcset="lower-bp-1200.jpg 1200w, lower-bp-800.jpg 800w">
   <img src="fallback.jpg" alt="…" sizes="calc(100vw - 2em)">
</picture>

当然,如果图片的比例会因所选的 <source> 元素而异,则会引发性能问题: <img> 仅支持单个 widthheight 属性,但省略这些属性可能会导致用户体验明显变差。 考虑到这一点,一个相对较近的节点,但 受到良好支持 - 是对 HTML 代码的补充 规范允许在 <source> 元素中使用 heightwidth 属性。这些工作同样有助于减少布局偏移 与在 <img> 上执行的操作一样,为选择的任何 <source> 元素在布局中预留相应的空间。

<picture>
   <source
      media="(min-width: 800px)"
      srcset="high-bp-1600.jpg 1600w, high-bp-1000.jpg 1000w"
      width="1600"
      height="800">
   <img src="fallback.jpg"
      srcset="lower-bp-1200.jpg 1200w, lower-bp-800.jpg 800w"
      sizes="calc(100vw - 2em)"
      width="1200"
      height="750"
      alt="…">
</picture>

请务必注意,艺术指导不仅仅可用于根据视口大小做出决策,而且应该考虑到 对大多数此类情况而言,使用 srcset/sizes 可以更高效地处理。例如,更好地选择图片来源 以符合用户偏好的配色方案:

<picture>
   <source media="(prefers-color-scheme: dark)" srcset="hero-dark.jpg">
   <img srcset="hero-light.jpg">
</picture>

type 属性

借助 type 属性,您可以使用 <picture> 元素的单一请求决策引擎仅传送图片格式 支持的浏览器

正如您在图片格式和压缩一文中所述,浏览器无法解析的编码甚至无法识别为 图片数据。

引入 <picture> 元素之前,传送新图片格式的最可行的前端解决方案需要 浏览器先请求并尝试解析图片文件,然后再确定是否舍弃该图片并加载后备图片。答 常见示例是以下几行的脚本:

   <img src="image.webp"
    data-fallback="image.jpg"
    onerror="this.src=this.getAttribute('data-fallback'); this.onerror=null;"
    alt="...">

使用此模式时,系统仍会在每个浏览器中发出 image.webp 请求,这意味着对浏览器传输造成浪费 对 WebP 的支持。如果浏览器无法解析 WebP 编码,就会抛出 onerror 事件,并交换 将 data-fallback 值转换为 src。这是一种浪费时间的解决方案,但同样,像这个方法 前端可用请记住,在任何自定义脚本发出一个请求前, 因此我们无法抢占此进程的机会。

<picture> 元素已明确设计以避免这些冗余请求。但浏览器仍然没有办法 type 属性会在未请求的情况下识别它不支持的格式,就会向浏览器发出关于来源的警告 以便其决定是否发出请求。

type 属性中,您需要提供媒体类型(以前称为 MIME 类型) 每个 <source>srcset 属性中指定的图片来源。这可以为浏览器提供 需要立即确定是否可以对该 source 提供的候选图像进行解码,而无需将任何外部 请求 - 如果媒体类型无法识别,系统会忽略 <source> 及其所有候选对象,浏览器会继续运行。

<picture>
 <source type="image/webp" srcset="pic.webp">
 <img src="pic.jpg" alt="...">
</picture>

在这里,任何支持 WebP 编码的浏览器都可以识别 type 属性中指定的 image/webp 媒体类型 <source> 元素中,选择该 <source>,并且由于我们只在 srcset 中提供了一个候选字词,因此可指示内部 <img>,用于请求、传输和呈现 pic.webp。任何不支持 WebP 的浏览器都将忽略 source,并且 如果没有任何相反的指令,<img> 将像自 1992 年以来那样渲染 src 的内容。 当然,您不需要在此处使用 type="image/jpeg" 指定第二个 <source> 元素,您可以假定 JPEG 普遍支持。

无论用户处于何种浏览环境,这一切都通过单次文件传输来实现,并且不会在互联网上浪费带宽 无法渲染的图片来源这也具有前瞻性意义:随着新文件格式的不断涌现, 和自己的媒体类型,得益于 picture,我们能够充分利用它们 - 无需 JavaScript,也无需服务器端 <img> 的所有速度。

自适应图片的未来

此处讨论的所有标记格式都是在标准化方面涉及的一大进步: 像 <img> 这样成熟且核心的网络内容绝非易事,这些更改旨在解决 至少可以说,它非常广泛。如果您发现自己认为这些方面还有很大的改进空间, 您完全正确从一开始,这些标准就是为了提供未来基准 技术来作为构建基础。

所有这些解决方案都必须依赖于标记,以便包含在来自服务器的初始载荷中, 并及时到达浏览器以请求图片来源,这一限制导致了 sizes 属性不合理。

但是,由于 Web 平台引入了这些功能,因此又引入了延迟图片请求的原生方法。 只有在页面布局已知之后才会请求具有 loading="lazy" 属性的 <img> 元素,以便延迟 在用户初始视口范围外的图片请求,直到稍后呈现网页的过程中,这样可能可以避免 不必要的请求由于浏览器在发出这些请求时已完全理解网页布局,因此 有人提议将 sizes="auto" 属性作为 HTML 规范的补充 在这些情况下,可以避免手动编写 sizes 属性的繁琐工作。

此外,还向地平线添加了 <picture> 元素,以匹配一些非常激动人心的更改 页面布局样式的方式虽然视口信息是制定高级布局决策的可靠依据, 让我们无法采用完全组件级的方法进行开发,也就是说, 网页布局的任何部分,其样式与组件本身所占空间相符。这种担忧导致 到创建容器查询:一种设置元素样式的方法 父级容器的尺寸,而不是单独使用视口。

虽然容器查询语法刚刚稳定,对浏览器的支持也非常有限, - 添加支持此 API 的浏览器技术将为 <picture> 元素提供 执行相同操作的方法:一个潜在的 container 属性,允许根据 <source> 选择条件 <picture> 元素的 <img> 占据的空间,而不是根据视口的大小。

如果您觉得这听起来有点含糊,这肯定有一个充分的理由:虽然这些网络标准的讨论一直在不断进行,但还远远未达成,您 尚无法使用

尽管与任何网络技术一样,响应式图片标记可以保证使用起来会越来越简单,但仍有一些 各种服务、技术和框架,以帮助减轻手写此类可用标记的负担。在下一单元中 我们将介绍如何将学到的图片格式、压缩和自适应图片方面的所有知识集成到现代开发工作流中。