前言
在用户界面中使用图像和动画已成为现代 Web 应用程序中的常见情况。尽管这些现代设计都致力于改善应用程序的用户体验,但如果这些图像在所有设备上都没有良好的响应,事情就会适得其反。
作为开发人员,我们必须满足所有这些要求。但大多数时候,由于我们正在寻求更高级别的解决方案,因此会忽略一些可能会带来巨大影响的小事。
在 picture 标签和 img 标签之间做选择可能是一个很小的决策,但如果你做出了正确的选择,就能改善用户体验和性能。
img 标签现在已经不够优秀
众所周知,很长一段时间以来,img 标签一直是 HTML 的核心元素之一,它的简单性和可用性是毋庸置疑的。
然而,随着各种屏幕尺寸、分辨率的设备和复杂用户需求的发展,img 标签的响应性和在多设备应用中使用的能力开始受到质疑。
所有这些问题可以归结为两大方面:
-
分辨率切换——为小屏幕设备提供较小尺寸图像的问题。 -
图像切换——在不同屏幕上显示不同图像的问题。
sizes:
表示资源大小的以逗号隔开的一个或多个字符串。每一个资源大小包括:
- 一个媒体条件。最后一项一定是被忽略的。
- 一个资源尺寸的值。
资源尺寸的值被用来指定图像的预期尺寸。当srcset使用 'w' 描述符时,用户代理使用当前图像大小来选择srcset中合适的一个图像URL。 被选中的尺寸影响图像的显示大小(如果没有CSS样式被应用的话)。如果没有设置srcset属性,或者没值,那么sizes属性也将不起作用。
srcset:
以逗号分隔的一个或多个字符串列表表明一系列用户代理使用的可能的图像。每一个字符串由以下组成:
- 一个图像的 URL。
- 可选的,空格后跟以下的其一:
- 一个宽度描述符,这是一个正整数,后面紧跟 '
w' 符号。该整数宽度除以sizes属性给出的资源(source)大小来计算得到有效的像素密度,即换算成和x描述符等价的值。 - 一个像素密度描述符,这是一个正浮点数,后面紧跟 '
x' 符号。
如果没有指定源描述符,那它会被指定为默认的 1x。
在相同的 srcset 属性中混合使用宽度描述符和像素密度描述符时,会导致该值无效。重复的描述符(比如,两个源 在相同的srcset两个源都是 '2x')也是无效的。
使用w值时,src的值会被忽略
srcset和sizes如何计算图片大小?
公式:(图片预期大小 / srcset的w值)* 图片本身大小;
举栗子:
large.jpg 640 x 640;
small.jpg 220 x 220;
<img srcset="small.jpg 1x, large.jpg 2x" />
DPR=1:small.jpg;DPR=2:large.jpg;
large.jpg small.jpg

<img srcset="small.jpg 220w, large.jpg 640w" />
当屏幕宽度小于200时,展示的是small.jpg;大于200时,展示large.jpg;并且图片大小跟随屏幕宽度

在这里,图片默认size是100vw,当屏幕宽度<200时,会匹配中srcset的220w,即small.jpg(220*220);
当屏幕大于220时,会匹配srcset的640w,即large.jpg(640*640);
公式:(100vw / 220)* 220 = 100vw; 所以图片大小会跟随屏幕的宽度
500w和1000w都是随便给的
<img srcset="small.jpg 500w, large.jpg 1000w" />
屏幕宽度小于500时(此时为208),浏览器展示small.jpg且图片的大小为92px(图片本身尺寸为220*220px);

屏幕宽度大于500时(此时为504),浏览器展示large.jpg且图片的大小为323px(图片本身尺寸为640*640px);

当屏幕宽度<500时,会匹配中srcset的500w,即small.jpg(220*220);最终,图片大小(92)= (209 / 500)* 220
当屏幕>500时,会匹配srcset的1000w,即large.jpg(640*640);图片大小(323)= (504 / 1000)* 640
屏幕宽度小于500时(此时为256),浏览器展示small.jpg且图片的大小为48px(图片本身尺寸为220*220px);

屏幕宽度大于500时(此时为515),浏览器展示large.jpg且图片的大小为410px(图片本身尺寸为640*640px);

sizes属性会对srcset进行约束,先在sizes中获取图片的预期大小,然后在srcset匹配对应的图片资源。
当屏幕宽度<500时,图片预期大小应为110px。110会匹配到srcset中的500w,即small.jpg(220*220);最终图片大小(48)= (110 / 500)* 220
当屏幕>500时,图片预期大小应为640px。640会匹配srcset的1000w,即large.jpg(640*640);最终图片大小(410)= (640 / 1000)* 640
注:
<img srcset="small.jpg 500w, large.jpg 1000w" />
- 当屏幕宽度由小变大的过程中,图片会由small变为large;但是从大变小时,图片并没有切换。因为浏览器会默认选择已有的w值更大的图片。
- sizes属性书写时,注意顺序。
<picture>
source的srcset有w值,则默认大小为100vw;
source的srcset没有w值,默认大小为本身大小;
img的上一个source有w值,那么分辨率大小变化,可能会影响img的图片的大小;
<picture>
<source
srcset="small.jpg 500w, large.jpg 1000w"
sizes="(min-width: 400px) 640px, 220px"
/>
<img src="default.jpg" alt="" />
</picture>
上述代码,展示方式和img一样,屏幕小于400时,展示small.jpg,大于400展示large.jpg;
图片最终大小计算方式同上;
分辨率由大到小切换时,图片没有切换;
<picture>
<source srcset="large.jpg" media="(min-width: 800px)" />
<source srcset="small.jpg 500w" media="(min-width: 400px)" />
<img src="default.jpg" alt="" />
</picture>
屏幕400 ~ 800,small.png,大小:(100vw / 500)* 220,随屏幕变化;
屏幕大于800,large.png,大小为本身大小640,不随屏幕变化;
屏幕小于400,default.png,不随屏幕变化:
初始屏幕宽度<400时,展示default图,大小为本身大小;
初始屏幕宽度>400时,展示small或large,修改屏幕宽度至<400,default图大小受上一个source的w值影响,最终大小:(400 / 500) * 700;
<picture>
<source srcset="large.jpg 500w" media="(min-width: 800px)" />
<source srcset="small.jpg" media="(min-width: 400px)" />
<img src="default.jpg" alt="" />
</picture>
屏幕400 ~ 800,small.png,大小为本身大小,不随屏幕变化;
屏幕大于800,large.png,大小为(100vw / 500)* 640,随屏幕变化;
屏幕小于400,default.png,不随屏幕变化:
初始屏幕宽度<400时,展示default图,大小为本身大小;
初始屏幕宽度>400时,展示small或large,修改屏幕宽度至<400,由于上一个source没有w值,所以大小仍然为本身大小;
- 使用 media 属性定义使用这些源的不同媒体条件
如果屏幕方向是横向,则浏览器将显示第一组图像;如果屏幕方向是纵向,则浏览器将使用第二组图像。
<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>
|