我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...

响应式图片的最好处理方案究竟是什么呢?动态更改图片的显示尺寸(width/height属性)么?还是要动态更改图片的地址?本文将要讨论其中的一个可能是最好的响应式图片方案:imgsrcSet属性。

苏南大叔:解读响应式网页中的响应式图片srcset+sizes处理方案 - srcset-sizes响应式图片
解读响应式网页中的响应式图片srcset+sizes处理方案(图6-1)

苏南大叔的“程序如此灵动”博客,记录苏南大叔和计算机代码的故事。事先说明的是,这个srcSet的概念表面上看很好理解,但是图片切换的理由和时机就非常难以理解了。测试环境:firefox@108.0.1chrome@108.0.5359.125

测试环境

首先要声明一下本文的测试环境,谷歌浏览器vs火狐浏览器。本文的测试代码是imgsrcSet属性。期待的测试结果是:代码会根据浏览器的情况(视口宽度或者密度比)的变化而变化。

然而,谷歌浏览器的情况不容乐观。虽然会根据情况第一时间选择合适的图片地址,但是存在的问题是会缓存这个图片选择结果。在页面刷新前,无论相关的实际情况如何变化,都不会再次更改图片,也就是失去了响应。目前【稍稍有点改善】的方法就是:打开谷歌浏览器的开发者模式,然后点击network里面的“禁用缓存”选项(其他禁用缓存的方法无效)。

苏南大叔:解读响应式网页中的响应式图片srcset+sizes处理方案 - 谷歌浏览器f12禁用cacahe
解读响应式网页中的响应式图片srcset+sizes处理方案(图6-2)

目前网络上的大部分攻略都表示:不知道选择某个图片的理由,是浏览器的自主行为。目前,使用市场上具有统治地位的谷歌浏览器就是无法解释,因为它的缓存结果太强大了,对srcSet的支持不好。

所以,为了更好的理解srcSet的工作原理,本文的测试环境破天荒的改为了火狐浏览器。在这个浏览器下面,可以最好的演示和理解整个图片切换过程。

基本框架原则

响应式图片方案就是在img标签上面增加了特殊的srcSetsizes来控制图片的显示的。例如:

<img src="0.png"
  srcset="1.png 500w, 2.png 800w, 3.png 1200w"
  sizes="(max-width:600px) 300px, 900px"
/>
  • 图片是很多张图片(理论上来说区别是像素密度清晰度的不同),只是对这些图片进行了动态切换。
  • srcSet属性,规定最基础的切换规则。尺寸的单位必须是w(别的尺寸不生效),理解为日常最常用的px
  • sizes属性可以不规定,主要的切换逻辑都存在于srcSet里面,它只是对srcSet属性的切换条件的再加工。而且,sizes内部使用px单位,而不使用w单位。

苏南大叔总结如下(经验总结,目前网络上无此描述):

srcset中的w为单位的数值 = 视口px宽度 * 硬件密度比

下面通过不同的例子来对上述原则,进行理解。

根据视窗宽度选择

根据视窗的宽度的不同来切换图片的地址属性,这个是非常经典的操作。css通常也是利用media媒体查询视口宽度,进而修改页面样式来实现响应式设计的。

本文中的所有图片真实的尺寸都是100px宽。

img {
  width: 100px;
}

第一个例子【推荐】

<img srcset="1.png 550w, 2.png 850w, 3.png 1050w" src="0.png" />

这段代码中,定义了三个图片地址,每个地址后面都(必须)使用w单位定义了一个宽度。

上述例子中,宽度实际上就是个切换图片的临界值,规定的区间是:

视窗宽度区间响应式图片的实际取值
(0,550/像素比]1.png
(550/像素比,850/像素比]2.png
(850/像素比,1050/像素比]3.png
(1050/像素比,正无穷大]3.png

注意:取值区间一边是小括号,另外一边是中括号。像素比一般来说,电脑设备一般取值为1。而手机设备一般取值不为1。

苏南大叔:解读响应式网页中的响应式图片srcset+sizes处理方案 - 截图1
解读响应式网页中的响应式图片srcset+sizes处理方案(图6-3)

第二个例子【败笔】【混乱】

第二个例子,在这个例子中,在srcSet后面增加了一个没有规定w的地址,导致全部逻辑被颠覆。

<img srcset="1.png 550w, 2.png 850w, 3.png 1050w, 4.png" src="0.png" />

测试结果:

所有的w为单位的宽度值,
1)当密度比为1的时候,视口宽度只有确切的等于这个值(除以密度比1)的时候,才会显示对应的图片,而不是原来的区间。
2)当密度不为1的时候,表现为一个很奇怪的区间,真的很奇怪。

视窗宽度区间响应式图片的实际取值
(0,550/像素比]1.png
(550/像素比,850/像素比]2.png
(850/像素比,1050]3.png
(1050,正无穷大]4.png

根据密度比进行选择

picture的密度比切换方案测试中,失败了。但是在img的密度比测试方案中,是成功的。而且恒定解释为一个区间,并不会出现解释为某个确切值的情况。

<img srcset="1.png 1x, 2.png 2x, 3.png 3x" src="0.png" />
实际的设备中,清晰度的衡量值:像素比并不恒定为整数。(用js去监测的话,表现为window.devicePixelRatio

测试结果是:

像素比区间取值
(0,1]1.png
(1,2]2.png
(2,3]3.png
(3,正无穷大]3.png
这里如果在最后增加一个没有定义像素比的图片地址的话,无效直接忽略即可。

苏南大叔:解读响应式网页中的响应式图片srcset+sizes处理方案 - 切换像素比看效果
解读响应式网页中的响应式图片srcset+sizes处理方案(图6-4)

增加sizes属性

sizes属性就是来搅局的,只规定srcSet属性就可以完美表述和切换了。但是,非要在这个srcSet属性的基础上再叠加一个sizes来再添变数。srcSet不是规定的被选择的标准么?size是规定选择的结果的,直接制定结果。

sizes可以直接规定值,以w为单位。实际上表述的值,和srcSet中的以w为单位的值,实际上是乘以密度比的关系。

sizes中的px值 * 密度比 = srcSet中的w值

测试例子如下:

<img
  srcset="1.png 550w, 2.png 850w, 3.png 1050w"
  sizes="(max-width:800px) 200px,600px"
  src="0.png"
/>

这个表述的区间是:

实际像素比sizes规定:视口宽度px视同srcset中的值落入srcset区间最终结果
1(0,800]200*像素比(0,5501.png
1(800,无穷大]600*像素比(550,850]2.png
2(0,800]200*像素比(0,550]1.png
2(800,无穷大]600*像素比(1050,无穷大]3.png
3(0,800]200*像素比(550,850]2.png
3(800,无穷大]600*像素比(1050,无穷大]3.png
视窗宽度区间响应式图片的实际取值
(0,550/像素比]1.png
(550/像素比,850/像素比]2.png
(850/像素比,1050]3.png
(1050,正无穷大]4.png

苏南大叔:解读响应式网页中的响应式图片srcset+sizes处理方案 - sizes推断
解读响应式网页中的响应式图片srcset+sizes处理方案(图6-5)

无效或错误表述

以下都是无效或者错误表述:

错误一:没写默认的src,兼容性。

<img srcset="1.png 550w, 2.png 800w"/>

错误二:srcSet有个单独的无条件图片地址,会引起混乱。

<img srcset="1.png 550w, 2.png" src="0.png"/>

错误三:srcSet中使用px表述,无效。

<img srcset="1.png 550px, 2.png 800px" src="0.png"/>

错误四:srcSet使用像素比表述时,定义了有个单独无效的表述,虽然不会导致混乱。

<img srcset="1.png 1x, 2.png" src="0.png"/>

错误五:sizes表述中错误使用了w单位,导致sizes属性整体失效。

<img srcset="1.png 500px, 2.png 800px" sizes="600w" src="0.png"/>

错误六:使用像素比描述的时候,试图使用sizes去改写条件,无效。

<img srcset="1.png 1x, 2.png 2x, 3.png 3x" sizes="(max-width:800px) 2x,1x" src="0.png"/>

js检测手段

监测是否支持srcset

'srcset' in HTMLImageElement.prototype 
'sizes' in HTMLImageElement.prototype 

检测视窗宽度:

document.body.clientWidth

检测设备密度比:

window.devicePixelRatio

检测当前图片的src

document.getElementsByTagName("img")[0].currentSrc

苏南大叔:解读响应式网页中的响应式图片srcset+sizes处理方案 - js代码检测
解读响应式网页中的响应式图片srcset+sizes处理方案(图6-6)

相关链接

响应式图片的处理方案,已经有以下几种:

看了很多文章,直到看到下面这篇文章,才明白更换浏览器的重要性。(不过,我这边的观点和这个链接文章也不一致)

结束语

苏南大叔经过不断的方案选择和对比,觉得picture+source的方案,更加好一些。毕竟谷歌浏览器里面也能顺利识别和流畅切换。更多html标签的解读,请参考苏南大叔的文章:

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   html5