<picture>
元素不会单独渲染任何内容,而是充当内部 <img>
元素的决策引擎。
用于指示要呈现的内容<picture>
遵循 <audio>
和 <video>
元素已设置的先例:封装容器元素
包含各个 <source>
元素。
<picture>
<source …>
<source …>
<img …>
</picture …>
该内部 <img>
还为不支持自适应图片的旧版浏览器提供了一种可靠的后备模式:
如果用户浏览器无法识别 <picture>
元素,系统会忽略该元素。然后,<source>
元素也会被舍弃,
因为浏览器根本无法识别这些键,或者如果没有 <video>
或 <audio>
父级,浏览器就无法获得有意义的上下文。
不过,任何浏览器都可以识别内部 <img>
元素,并且其 src
中指定的来源将按预期呈现。
“艺术指导”包含 <picture>
的图片
根据网页中图片的大小更改图片的内容或宽高比通常被称为“以艺术为导向”的
自适应图片。srcset
和 sizes
旨在以隐蔽的方式运行,根据用户的浏览器命令无缝替换源代码。
不过,您有时可能会想跨断点更改来源,以便更好地突出显示内容,就像调整网页布局一样。
例如:中心焦点较小的全宽标题图片可能在较大的视口上效果很好:
但在缩小以适应小视口时,图片的中心焦点可能会丢失:
这些图片来源的正文相同,但为了在视觉上更突出该正文,您需要添加 更改图像来源的比例。例如,将图片中心的放大范围较小;以及 裁剪掉边缘的部分细节:
这种“剪裁”的方式都可以通过 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
元素都与其 media
或 type
不匹配,则您应始终按顺序指定内部 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>
仅支持单个 width
和 height
属性,但省略这些属性可能会导致用户体验明显变差。
考虑到这一点,一个相对较近的节点,但
受到良好支持 - 是对 HTML 代码的补充
规范允许在 <source>
元素中使用 height
和 width
属性。这些工作同样有助于减少布局偏移
与在 <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>
占据的空间,而不是根据视口的大小。
如果您觉得这听起来有点含糊,这肯定有一个充分的理由:虽然这些网络标准的讨论一直在不断进行,但还远远未达成,您 尚无法使用
尽管与任何网络技术一样,响应式图片标记可以保证使用起来会越来越简单,但仍有一些 各种服务、技术和框架,以帮助减轻手写此类可用标记的负担。在下一单元中 我们将介绍如何将学到的图片格式、压缩和自适应图片方面的所有知识集成到现代开发工作流中。