响应式图像
<picture>
是HTML5元素,旨在为我们提供更多的功能和性能更好的响应图像功能。 Picture标签不会加载单个图像并尝试调整其大小以适合所有可能的视口尺寸和布局,而是加载不同大小和分辨率的多个图像,选择最适合不同场景的图像。
<picture>如何工作?
它的工作原理类似于这样<audio>
和<video>
元素的工作,让您可以将多个source
在父标签<picture>
元素,每一个使用srcset
和sizes
属性与条件一起指定不同的图像文件下,他们应该被加载。
但是,与<picture>
元素一样强大,有时它提供给我们的功能要比实现适当的响应能力所需的功能更多。 有时候,他的真正需要的是一个普通<img>
使用元素srcset
和sizes
属性内联。
在本教程中
在本教程中,我们将解决您可能遇到的任何困惑。 我们会看到什么srcset
和sizes
属性都可以做,如何将它们与使用<img>
或<picture>
元素,以及如何知道哪个组合是正确的选择。
使用以下链接跳至每个部分:
1.从默认的<img>元素开始
这是我们的起点,它是一个带有alt
属性的常规旧香草<img>
元素,用于提供基于文本的描述。
<img src="image.png"
alt="Image description">
在响应图像的基本级别上,通常将其与一点CSS配对,如果其父容器变得太小而无法容纳它,则允许该单个图像缩小:
img {
max-width: 100%;
height: auto;
}
这是确保图像尺寸不会显着错误的基本工作,但是无论哪种情况,无论哪种效果(差),它仍然只给我们提供一张图像。
它从一方面解决了问题,使我们可以在许多不同的情况下显示相同的图像。 但这不允许我们为不同的情况指定不同的图像。 例如,对于某些用户来说,原始图像很可能不切实际地很大(就文件大小而言),以便在他们的移动网络上下载。
提示 :看看我的网站费用是多少? 由Tim Kadlec撰写,旨在为全球用户了解移动数据的实际成本。
“根据HTTP Archive的2019年7月1日运行,中位站点现在重1937kb。” – 我的网站费用是多少?
要开始制定更好的解决方案,让我们继续进行srcset
。
2.如何对一组图像使用“ srcset”
可以在视口的大小上加载一组图像,为宽视口加载大图像,为窄视口加载小图像,而不是在各处仅使用一个图像,这会更好。
这就是srcset
属性的用途:一组图像,而不是通过src
属性的图像。
宽度切换
当仅使用常规src
属性加载图像时,浏览器直到加载后才知道图像的宽度。 但是,使用srcset
属性,我们可以提前告知浏览器每个图像的宽度。 然后,它可以使用该信息来加载最合适的图像,具体取决于当时视口的大小。
在使用srcset
时,您仍将使用src
属性,因为它提供了浏览器应该使用的默认图像,并且如果有人使用的是不支持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.
显示宽度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
示例,我们可能希望将图像以80vw
的宽度进行布局,以80vw
左右80vw
都有一些空白。 但是,如果视口足够宽(例如至少60rem
,我们可能只想保留其中的大部分视口。
我们可以通过更改代码以在80vw
大小之前添加媒体条件(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">
“大小”
不能直接确定“ srcset”图像的选择
请注意,在上面的示例中,无论我们通过sizes
属性提供图像的布局如何,浏览器仍将自动选择最适合的图像,就像在添加任何媒体条件之前所做的一样。
您可能会看到它说您应该使用sizes
srcset
媒体条件来确定应该从srcset
的列表中加载哪个图像。 这是间接的情况,但是以这种方式考虑功能可能无济于事。
我之所以这样说,是因为您可能会认为您需要使用与常规媒体查询中使用的sizes
的媒体条件,即指定特定的媒体条件以触发要加载的每个图像。 但是,这并不是这里的工作方式。
而是,浏览器总是会自动处理图像选择。
真正发生的是,您说的是sizes
:
“在[此]视口大小下,我想要一个[那个]宽的图像槽。”
您并不是要说要加载哪个特定图像文件,而是要创建一个一定大小的占位符“插槽”以适合您的布局。
使用srcset
您说的是:
“这是我的照片,选择您认为最合适的照片。”
浏览器将根据您的sizes
属性生成空的图像“插槽”,然后从srcset
选择最合适的图像以填充它们。
乍一看,您的插槽大小和图像宽度似乎不一定紧密对应。 你可能在你的四象srcset
并在只有两个灵活大小的“槽” sizes
,仍然可以在浏览器不同的时间使用的所有四个图像。
我们在前面的示例中看到了类似的内容,其中创建了一个“ slot”大小,该大小在40rem
和60rem
视口宽度之间40rem
并60rem
了一个90vw
的图像。
因此,此广告位的此像素宽度可以计算为大约570px
至860px
之间的任何860px
。 在我们的示例中,我们提供了宽度为320px
, 800px
和1200px
。
浏览器通常会从srcset
中选择最小的图像,该图像仍然比当前的“插槽”宽。 因此,如果“广告位”的宽度为810px
,则将加载1200px
图像,但是如果广告位的宽度为790px
,则将加载800px
图像。 一个媒体条件,两个可能的图像。
放置sizes
影响从srcset
选择哪个图像的唯一原因是,它更改了浏览器试图最适合的“插槽”的大小。 但是,这两个概念仍然是非常分开的,应该这样考虑。
总结一下:
- 首先,将您的图像布局视为一系列占位符插槽,然后确定这些插槽的大小。
- 然后,创建一组宽度最适合您决定创建的插槽的图像。
4.何时使用<picture>标签
到目前为止,我们已经谈论了很多关于srcset
和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>
require格式:
<picture>
<img src="image-small.png" alt="Image description">
</picture>
为了重新介绍srcset
和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>
元素中,我们可以通过添加一个带有值(orientation: landscape)
的media
属性来实现
<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
属性仅包含一个媒体条件,并且只有当其值为true时,它所附加的<source>
元素才会激活。
补充说明:我已经看到它表示您不应同时使用<source>
元素上的media
和sizes
属性,但是我在规范中并未对此进行验证,在我的测试中,两者似乎可以协同工作。
<source>订单事项
构造<picture>
元素时,请注意以下事实:浏览器一击到具有media
属性且返回true的<source>
元素,它将停止查找并从该元素的srcset
呈现。 因此,请确保首先将具有较高特异性的媒体查询放在首位。
例如,我们刚刚提到了让<source>
元素与媒体查询一起查找横向和min-width
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>
元素后立即检查文件类型支持。
关于可访问性的说明
屏幕阅读器将使用后备<img>
元素中提供的alt
文本,用于浏览器中显示的任何图像。 因此,请确保alt文字能很好地代表所有图像!
6.浏览器对<picture>的支持
如今, 浏览器对 <picture>
元素的 支持非常可靠,尽管与现代CSS和HTML的许多其他方面一样,Microsoft依靠Edge浏览器(而不是IE)来提高团队色彩。
通过使用<picture>
的后备<img>
标签,您仍可以使用不支持的浏览器来满足任何人的需求。
结论
之间srcset
, sizes
和<picture>
我们有超过你的React令人难以置信的图像和强大的全面控制,并带来了新的文件格式在与优雅降级阶段的能力。
srcset
在您的项目中尝试srcset
, sizes
和<picture>
,看看您的想法!
响应式图像