<picture> 是一个 html5 元素,旨在为咱们提供更多通用和高性能的响应式图像功能。图片标签不是加载单个图像并尝试调整其大小以适应所有可能的视口大小和布局,而是加载多个不同大小和分辨率的图像,选择最适合不同场景的图像。
<picture> 是如何工作的?
<audio> 它的工作方式与 元素的工作方式类似<video> ,允许您 source 在父 <picture> 元素中放置多个标签,每个标签都使用 srcset 和 sizes 属性来指定不同的图像文件以及加载它们的条件。
然而,尽管 <picture> 元素很强大,但有时它为咱们提供了比实现适当响应所需的实际更多的权力。有时它真正需要的只是一个 使用 和 属性内联的常规<img> 元素 。srcsetsizes
在本教程中出现
在本教程中,咱们将解决您可能遇到的任何困惑。咱们将看到 srcset and sizes 属性可以做什么,如何将它们与 <img> or <picture> 元素一起使用,以及如何知道哪种组合是正确的选择。
目录:
从默认 <img> 元素开始
如何对一组图像使用“srcset”
使用“尺寸”控制图像布局
何时使用 <picture> 标签
如何使用<图片>
<picture> 的浏览器支持
1. 从默认的 <img> 元素开始
这是咱们的起点,一个 <img> 带有 alt 属性的普通旧 vanilla 元素,用于提供基于文本的描述。
<img src="image.png" alt="Image description">
在响应式图像的基础级别,这通常与一些 css 配对,如果其父容器变得太小而无法容纳它,则允许单个图像缩小:
img {
max-width: 100%;
height: auto;}
这完成了确保图像大小不会严重错误的基本工作,但它仍然让咱们在所有情况下都只有一张图像,无论一张图像的效果如何(或差):
它在一个方面解决了这个问题,允许咱们在许多不同的情况下显示相同的图像。但它不允许咱们为不同的情况指定不同的图像。例如,对于某些用户在他们的移动网络上下载的原始图像(就文件大小而言),很有可能是不切实际的。
提示:看看 我的网站费用是多少? 通过 Tim Kadlec 了解 全球用户移动数据的实际成本。
“根据 2019 年 7 月 1 日的 HTTP Archive 运行,站点的中值现在重 1937kb。” – 我的网站费用是多少?
要开始制定更好的解决方案,让咱们继续 srcset。
2. 如何对一组图像使用“srcset”
如果咱们可以根据视口的大小加载一组图像,而不是在任何地方只使用一个图像,那就更好了,为宽视口加载大图像,为窄视口加载小图像。
这就是 srcset 属性的用途:一 组 图像,而不仅仅是一个通过 src 属性。
宽度切换
当仅使用常规 src 属性加载图像时,浏览器直到 加载后才知道 它的宽度。但是通过这个 srcset 属性,咱们可以提前告诉浏览器咱们每张图片的宽度。然后,它可以使用该信息根据当时视口的大小加载最合适的图像。
使用时您仍将使用该 src 属性, srcset 因为它提供了浏览器应使用的默认图像,并在有人使用不支持 srcset.
移动优先
在这里遵循移动优先方法并通过 src 属性加载最小的图像是个好主意。然后将您的默认图像及其较大的替代图像 srcset 作为逗号分隔列表添加到属性中,指定每个的宽度,(在空格之后),使用 [width]w:
<img src="image-small.png"
srcset="image-small.png 320w, image-medium.png 800w, image-large.png 1200w"
alt="Image description">
尽管您可能听说过相反的建议,但将默认图像 srcset 及其宽度包括在内很重要,否则浏览器不会将其包含在可供选择的选项列表中,因此它永远不会以任何视口宽度加载。
使用上面的代码,浏览器将以小视口大小加载小图像,以中等视口大小加载中等图像,在大视口大小加载大图像。(非常粗略地描述视口大小)。
如果浏览器不支持 srcset, (这只是相当老的浏览器的问题),它将回退到显示小图像。如果您的项目需要为旧版浏览器提供服务,请确保包含一些 CSS 以将默认图像缩放到正确的大小。
注意: 尽管上面的代码将按原样工作,但根据 srcset 属性规范 ,如果您 srcset 用于宽度切换,您还必须包含一个 sizes 属性,咱们将在稍后讨论。
像素密度切换
您也可以使用 srcset 根据其 DPI 加载图像,但不指定它们的宽度,您应该显示它们的像素密度,表示为 [density]x:
<img src="image-defaultdpi.png"
srcset="image-hidpi.png 2x, image-higherdpi.png 4x"
alt="Image description">
但是,您不能在同一 srcset 属性中使用像素密度和宽度,也不能将像素密度规范与 sizes 咱们即将添加到组合中的属性一起使用。出于这个原因,您通常更可能会发现您希望在 srcset 属性中使用宽度规范。
3.使用“尺寸”控制图像布局
该 sizes 属性允许您指定图像布局的宽度。请注意,这是与 srcset 属性中每个文件指定的实际图像宽度不同的概念。中给出的宽度 sizes 仅与布局有关,可以认为是创建空的占位符插槽,浏览器可以在其中插入来自 srcset.
浏览器选择从您的 加载哪个图像文件都没有关系 srcset,它会以您在 中指定的宽度显示它 sizes.
例如,如果您希望图像始终显示在视口宽度的 80% 处,您可以使用:
<img src="image-small.png"
srcset="image-small.png 320w, image-medium.png 800w, image-large.png 1200w"
sizes="80vw"
alt="Image description">
注意: 百分比值是不允许的,但 vw (视口宽度)值是允许的。
在此示例中,浏览器仍将根据视口的大小在小、中和大图像之间进行选择,但无论选择哪个图像,它都会以 80vw.
添加媒体条件
在上面的示例中,咱们只在 sizes 属性中使用了一个值,但您可以通过添加“媒体条件”来有条件地更改图像布局。 媒体条件 是咱们在使用媒体查询时评估的真或假状态,并且在评估时 sizes 允许您根据视口宽度等不同的方式布置图像。
例如,根据咱们之前的示例,咱们可能希望图像的布局宽度为 , 80vw 因此其左右两侧都有一些空白空间。但是,如果视口足够宽,咱们可能只想保留这么多的视口,比如至少 60rem.
咱们可以通过更改代码 (min-width: 60rem) 在咱们的 80vw 尺寸之前添加媒体条件来实现这一点,如下所示:
<img src="image-small.png"
srcset="image-small.png 320w, image-medium.png 800w, image-large.png 1200w"
sizes="(min-width: 60rem) 80vw"
alt="Image description">
80vw 现在,仅当视口至少 60rem 宽时,图像才会被调整大小 。
100vw 如果视口不满足咱们刚刚添加的媒体条件,咱们也可以将咱们的图像布局默认为宽度 。因为默认值 sizes 不需要媒体条件,所以咱们需要做的就是 100vw 在逗号后添加值:
<img src="image-small.png"
srcset="image-small.png 320w, image-medium.png 800w, image-large.png 1200w"
sizes="(min-width: 60rem) 80vw,
100vw"
alt="Image description">
如果咱们选择,咱们还可以在两者之间添加另一个尺寸和媒体条件,以便当视口变窄时, 40rem 咱们将长度设置为 90vw:
<img src="image-small.png"
srcset="image-small.png 320w, image-medium.png 800w, image-large.png 1200w"
sizes="(min-width: 60rem) 80vw,
(min-width: 40rem) 90vw,
100vw"
alt="Image description">
“sizes”不直接决定“srcset”图像选择
请注意,在上面的示例中,无论咱们通过 sizes 属性为图像提供何种布局,浏览器仍会自动选择最适合的图像,就像咱们添加任何媒体条件之前所做的那样。
您可能会看到它说您应该使用媒体条件 sizes 来确定应该从 srcset. 这是间接的情况,但以这种方式考虑功能可能没有帮助。
我这么说的原因是您可能会认为您需要以 sizes 您在常规媒体查询中使用它们的方式使用媒体条件,即指定一个特定的媒体条件来触发您要加载的每个图像。然而,这并不是这里的工作方式。
相反,浏览器总是会自动处理图像选择。
真正发生的是 sizes 你说:
“在 [这个] 视口尺寸下,我想要一个 [那个] 宽的图像槽。”
您并不是说要加载哪个特定的图像文件,只是要创建一个特定大小的占位符“插槽”以适合您的布局。
和 srcset 你一起说:
“这是我的照片,选择你认为最好的一张。”
浏览器会根据你的 sizes 属性生成空的图像“槽”,然后从你那里选择最合适的图像 srcset 来填充它们。
一目了然,您的插槽大小和图像宽度似乎不一定紧密对应。您可能有四个图像, srcset 并且只有两个灵活大小的“插槽”, sizes 但浏览器仍然可以在不同时间使用所有四个图像。
咱们在前面的示例中看到了类似的情况,咱们创建了一个在 视口宽度40rem 和 60rem 视口宽度之间处于活动状态的“插槽”大小,并以 90vw.
因此,这个槽的像素宽度可以计算到大约 570px 和 之间的任何值860px。在咱们的示例中,咱们提供了宽度为 320px和 800px 的 图像1200px。
浏览器通常会从 srcset 仍然比当前“槽”宽的图像中选择最小的图像。因此,如果“槽”的宽度为 10 , 810px 它将加载 1200px 图像,但如果 “槽”的宽度为 ,790px 则它会加载 800px 图像。一种媒体条件,两种可能的图像。
sizes 您输入的内容会影响从哪个图像中选择 的唯一原因 srcset 是它改变了浏览器试图最适合的“插槽”的大小。但是这两个概念仍然是完全不同的,应该这样考虑。
所以总结一下:
首先, 将您的图像布局视为一系列占位符插槽,并确定这些插槽的大小。
然后, 创建一组宽度最适合您决定创建的插槽的图像。
4. 何时使用 <picture> 标签
到目前为止,咱们已经讨论了很多关于 srcset and 的内容sizes,您可能想知道, <picture> 元素呢?
用于“艺术指导”而不是“分辨率切换”
到目前为止,在咱们的示例中,咱们纯粹是在宽度或像素密度可能不同的集合中交换图像,但在每种情况下纵横比和方向保持相同。这称为“分辨率切换”。
但有时你想做的还不止这些。有时您希望包含图像以供浏览器选择,这些图像以不同的方式裁剪,或者您可能希望同时提供横向和纵向选项。
将这些类型的图像添加到组合中被称为“艺术指导”,这就是 <picture> 元素发挥作用的地方,在咱们目前所看到的之上添加另一层响应式图像功能。
<picture> 完全能够处理分辨率切换,但是如果你只需要它,你不应该使用它。在这种情况下,坚持使用常规 <img> 元素加 srcset 和 sizes。但是,如果您也需要艺术指导,那就是 <picture> 时候了。
用于部分支持的图像格式
除了 <picture> 用于艺术指导之外,您还可以在想要部署 webp 等较新的图像格式但仍回退到完全支持的格式(如 PNG)时使用它。咱们很快就会看到。
5.<picture>使用方法
<picture> 元素本身什么都不做。 相反,它旨在环绕一个 <img> 元素和一个或多个 <source> 元素。这些 <source> 元素为浏览器提供了更多信息,以帮助它决定应该通过 <img> 元素呈现哪个文件以及以什么大小呈现。
该 <picture> 元素的子 <img> 元素是必需的,并且该子元素不应 具有 自己的 属性srcset 和 sizes 属性,因为该功能将转移到该 <source> 元素。此外, <img> 元素 还必须 具有 src 和 alt 属性。因此,让咱们将到目前为止咱们放在一起的示例代码并将其转换为所需的格式 <picture> :
<picture>
<img src="image-small.png" alt="Image description"></picture>
为了重新引入咱们在 srcset and sizes 属性中的功能,咱们可以添加一个 <source> 具有相同属性的元素,如下所示:
<picture>
<source
srcset="image-small.png 320w,
image-medium.png 800w,
image-large.png 1200w"
sizes="(min-width: 60rem) 80vw,
(min-width: 40rem) 90vw,
100vw">
<img src="image-small.png" alt="Image description">
</picture>
一切都恢复了,但正如咱们之前提到的, <picture> 如果咱们所做的只是分辨率切换,那么使用它是没有意义的。所以让咱们假设咱们当前加载的所有图像都是横向的,然后咱们将添加第二组图像以用于纵向。
咱们要做的第一件事是指定咱们当前的图像集只应在视口处于横向时使用。在咱们的 <source> 元素中,咱们可以通过添加 media 具有值的属性 来做到这一点(orientation: landscape)
<picture>
<source
media="(orientation: landscape)"
srcset="image-small.png 320w,
image-medium.png 800w,
image-large.png 1200w"
sizes="(min-width: 60rem) 80vw,
(min-width: 40rem) 90vw,
100vw">
<img src="image-small.png" alt="Image description">
</picture>
从这里,咱们可以添加第二个 <source> 元素,该元素仅在站点处于纵向时才会激活。这个元素将提供一个新的 srcset,具有新的图像宽度,但仍将使用与 sizes 以前相同的布局。这样,咱们将在不同视口尺寸的图像两侧保持相同数量的空白空间:
<picture>
<source
media="(orientation: landscape)"
srcset="image-small.png 320w,
image-medium.png 800w,
image-large.png 1200w"
sizes="(min-width: 60rem) 80vw,
(min-width: 40rem) 90vw,
100vw">
<source
media="(orientation: portrait)"
srcset="image-small-portrait.png 160w,
image-medium-portrait.png 400w,
image-large-portrait.png 600w"
sizes="(min-width: 60rem) 80vw,
(min-width: 40rem) 90vw,
100vw">
<img src="image-small.png" alt="Image description">
</picture>
好了,现在咱们将有纵向的纵向图像和横向的横向图像——随着咱们的分辨率切换,一些不错的艺术方向。
如果需要,咱们可以在此基础上进一步发展。例如,除了拥有一组常规的风景图像外,咱们还可以拥有 <source> 一组具有宽幅风景图像的元素。咱们可以将其设置为显示网站是否为横向 且 至少 1200 像素宽: media="(orientation: landscape) and (min-width: 1200px)"
注意: 虽然 media 和 sizes 属性都包含媒体条件,但它们的使用方式不同。该 sizes 属性专门用于创建布局大小的集合,并在每个条件后指定布局宽度。该 media 属性只包含一个媒体条件,只有当它评估为真时, <source> 它附加的元素才会激活。
附加说明: 我看到它说你不应该同时在一个元素上使用 media and sizes 属性 <source> ,但是我没有在规范中找到对此的验证,并且在我的测试中,这两者似乎可以很好地协同工作。
<translation> 订单事项
在构造 <picture> 元素时,请注意,一旦浏览器点击一个 <source> 具有返回 true 的属性的元素, media 它将停止查找并从该 srcset 元素呈现。因此,请确保首先放置具有更高特异性的媒体查询。
例如,咱们刚刚提到了让一个 <source> 带有媒体查询的元素同时查找横向和 a min-width of 的 选项1200px。如果您首先放置了一个 <source> 只需要横向方向的元素,它就会在浏览器有机会走得更远之前激活。所以在这个例子中不要这样做:
<picture>
<source media="(orientation: landscape)" ... >
<source media="(orientation: landscape) and (min-width: 1200px)" ... ></picture>
做这个:
<picture>
<source media="(orientation: landscape) and (min-width: 1200px)" ... >
<source media="(orientation: landscape)" ... ></picture>
对部分支持的文件类型使用 <picture>
事实上,它 <picture> 会遍历一堆 <source> 元素,直到找到可以成功加载的图像,这意味着您可以非常方便地使用它来加载尚未 100% 浏览器支持的新文件格式。
在此示例中,如果浏览器支持 WebP,它将按照第一个 <source> 元素中指定的方式加载。如果浏览器无法加载 WebP 图像,它将尝试从第二个 <source> 元素加载 svg。最后,如果两者都不支持,则 PNG 将改为加载:
<picture>
<source type="image/webp" srcset="illustration.webp">
<source type="image/svg+xml" srcset="illustration.svg">
<img src="illustration.png" alt="A hand-made illustration">
</picture>
您会注意到在此示例 type 中使用了该属性。当通过您加载替代文件格式时, <picture> 您应该以这种方式指定 MIME 类型,以允许浏览器在遇到相关元素时立即检查文件类型支持 <source> 。
关于可访问性的说明
屏幕阅读器将使用 在浏览器中显示的任何图像alt 的后备元素中提供的文本 。<img>因此,请确保替代文本同样好地代表所有图像!
6. <picture>的浏览器支持
如今,浏览器对<picture>元素的支持非常可靠,尽管与现代 CSS 和 html 的许多其他方面一样,微软依靠 Edge 浏览器而不是 IE 来发挥团队色彩。
通过在内部使用后备<img>标签,<picture>您仍然可以满足使用不支持浏览器的任何人的需求。
结论
之间 srcset, 咱们对您的响应式图像具有难以置信的强大和广泛的控制,并且能够以优雅的降级将新的文件格式带入舞台sizes
and <picture>
- <picture> 是如何工作的?
- 宽度切换
- 移动优先
- 像素密度切换
- 添加媒体条件
- “sizes”不直接决定“srcset”图像选择
- 用于“艺术指导”而不是“分辨率切换”
- 用于部分支持的图像格式
- <translation> 订单事项
- 对部分支持的文件类型使用 <picture>
- 关于可访问性的说明