img 标签的新属性Srcset应用
一、响应式图片srcset属性
说起图片的srcset
属性,估计有不少与时俱进的小伙伴会在心中不由自主念想道:“这个我知道的,可以根据屏幕密度现实对应尺寸图片,例如……”
<img src="mm-width-128px.jpg" srcset="mm-width-128px.jpg 1x, mm-width-256px 2x">
上面代码对应demo轻戳这里。当然,我们也可以简写成:
<img src="mm-width-128px.jpg" srcset="mm-width-256px 2x">
由于我们都不是“别人家”的公司,因此,我们的办公PC显示器默认设备像素比都是1
,因此,这些显示器呈现的图片默认都是128
像素宽度的。下面问题来了,(不是挖掘机哪家强),如何让屌丝显示器模拟高设备像素比呢?
然后,选择对应的设备,例如iPhone6 Plus的设备像素比就是3
.
此时,刷新页面,加载的就是大尺寸图片,也就是256像素宽度那张。
150%
:
window.devicePixelRatio
为1.5
,因此加载的就是256像素宽度的图片。有图有真相:
2x
对应图片,虽然两者图片大小差不多,但个人觉得还是2倍尺寸优化大图更好一点,为什么呢?
srcset
当初设计的用意是为了高密度屏幕上图片更好的显示,如果世界上就只有“不同设备密度”这一个戏剧冲突的话,2x
图片是高清图还是2倍尺寸图其实都无伤大雅。然而,事实上,生活无处不戏剧,现代web布局中,有种布局不可忽略,那就是「响应式布局」,剧本往往会这样,PC浏览器上显示大图,Mobile浏览器上显示小图。发现没,同样是“大小图的要求”,和设备像素比有类似的戏剧冲突。
于是,如果我们2x
图片使用的是高清图,结合响应式布局,我们可能需要4张图片资源,即:小图、小图高清和大图、大图高清。但是,2x
图片走的是2倍尺寸图片,我们只需要3张图片资源,即:小图、中图以及中图、大图。
在老一代srcset
规范成型过程中,其实已经考虑到与响应式布局的纠葛,出现了w
描述符,例如,走高清路线的:
<img src="small.jpg" srcset="small.jpg 640w 1x, small-hd.jpg 640w 2x, large.jpg 1x, large-hd.jpg 2x">
走2倍尺寸路线的:
<img src="small.jpg" srcset="small.jpg 640w 1x, medium.jpg 640w 2x, medium.jpg 1x, large.jpg 2x">
注意啊注意:千万不要去关心上面的w
描述符的含义,因为新的srcset
属性中w
描述符含义与之完全不同,为了避免理解冲突,心中跟我默念3遍:忘掉它、忘掉它、忘掉它,无视它、无视它、无视它。大家可以把精力放在下面,新的srcset规范以及新的sizes属性语法含义等。
二、恰如其分的时间点
srcset
属性的浏览器支持情况,会发现有黄黄绿绿的颜色:
可以看到,Chrome浏览器下,从版本38开始是绿色的,而之前是黄绿色。黄绿色表示仅支持旧的srcset
规范,绿色表示支持全新的srcset
规范,包括sizes
属性,w
描述符。
而Chrome 38稳定版就在上周发布(腾讯软件管家显示10月16号也就是前几天发布的),于是,我们就有条件实践srcset
新规范特性,有利于快速学习。
因此,我才选择在这个时间点写这篇文章,推产品也是如此,需要一个合适的时间点,太早的死在沙滩上,太晚的落后跟不上。
因此,若要学习本文内容,看看您的Chrome浏览器是否是38+.
于此同时,苹果刚发布了4x
的显示器,如果使用传统srcset,需要1x
,2x
, 3x
, 4x
,
我勒个去,HTML立马变成了臃肿的大胖子。与时俱进势在必行!
三、全新的智能srcset、sizes属性, w描述符
srcset
是人主导,而现在新的srcset
是浏览器主导,你主需要提供图片资源、以及断点,其他都交给浏览器智能解决,什么响应宽度啊、设备像素比啊,你都不要关心了,浏览器会自动匹配最佳显示图片。你的表情现在是不是这样子啊:
如下HTML示例:
srcset
用来指向提供的图片资源,注意,仅仅是资源指向,没有以前的1x
, 2x
什么的,这个都交给浏览器了,我们不需要关心!例如这里,指向了3个尺寸图片,分别实际尺寸128像素,256像素和512像素。
sizes
用来表示尺寸临界点,主要跟响应式布局打交道。语法如下:
sizes="[media query] [length], [media query] [length] ... etc"
例如上述代码中,size
= "(max-width: 360px) 340px, 128px"
表示当视区宽度不大于360像素时候,图片的宽度限制为340像素,其他情况下,使用128像素(对应下面demo页面第1张图)。
如果sizes="128px"
,
则尺寸就一直是128像素,图片只会根据设备像素比发生变化。
注意,这里所有的值都是指宽度值,且单位任意,em
,px
, cm
, vw
, ...
都是可以的,甚至可以CSS3的calc
计算(对应下面demo页面第2张图),例如:
sizes="(max-width: 360px) calc(100vw - 20px), 128px"
表示当视区宽度不大于360像素时候,图片宽度为整个视区宽度减去20像素的大小。
OK,上面2个属性具体如何起作用的呢?首先,你需要狠狠地点击这里:srcset与sizes新释义w描述符示意demo
其中fit
前面的钩钩去掉,以更清晰的显示。此时,大家可以看到,图片显示的是128像素宽度的。为什么呢?
sizes
属性值吗?最后光秃秃没有媒体查询的值就是128px
,
目前视图宽度是1024像素,远远大于360像素这个临界宽度值,因此,图片占据宽度是128像素。同时,最最重要的是,这里的设备像素比是1
.
//zxx: 上下两张图上面已经提到过,代码差异仅仅是sizes
的一个临界宽度值不一样,上面的是340px
,下面的是calc(100vw
- 20px)
,有助于大家深入理解w
描述符,后面有大量戏份,当然,这里,大家可暂时不用关心。
1
改成2
然后刷新页面:
如果改成4+,还是上面这种512像素宽度的图片,因为这是我们给浏览器提供的最大w
对应的图片了。
大家注意到木有,我们完全没有指定浏览器那个设备像素比使用哪个图片,浏览器非常smart帮我们加载了最佳显示的图片。这就是最新的srcset
的释义,更智能更强大。
sizes
属性的作用机制。
360
像素,正好是sizes
设置的临界宽度值,修改设备像素比为1
(去除其他测试干扰因素),刷新页面,会发现页面加载的是512这张图:
为什么加载是512呢?
依次看来,首先第一张图,对应值是(max-width:
360px) 340px
, 意思通俗易懂,视区宽度不大于360
像素时候,图片实际尺寸340
像素。此demo两侧各有10像素空白,因此,正好图片满屏显示的感觉。下面问题来了,为什么加载的是512这种图,而不是256?
大家还记不记得srcset
中每张图片资源后面的w
描述符的值大小?没错,分别是128w
,256w
, 512w
.
正好这里解释下w
描述符的意思,根据我个人的理解(注意,是个人理解,仅供参考),w
用来描述文件的宽度,我们可以形象理解为规格,就像手机一样,有大小不一样的尺寸与规格。根据我浅薄的经验,我们可以直接等同于像素去理解。可能你会疑问,那为何不直接256px
而是256w
,
因为,请注意,这里的256w
并不是指图片的宽度,而是图片的宽度规格,例如,一张图片实际宽度是256像素,但是,这种图片是png24无损图片,或100%质量JPG图片,则,我们可以使用512w
表示这张图片,质量好规格就高,不难理解吧!如果是512px
显然就有问题了,明明图片256像素,搞个512px
,歧义到王母娘娘哪儿去了!因此,需要一个没人见过的w
表示,同时,需要意识到,w
不是单位,而是一个描述符(descriptor)。
回到主线,图片340像素,可以看出340规格,340w
,
于是256w
这张图片显示就规格不够,简称“不够格”;512w
> 340w
,满足最优显示准则,于是,加载的就是512px
这张图。
如果你希望视图360像素宽度时候加载的是256这张图片,很简单,修改其规格256w
为340w
,
done!
OK, 注意注意,前方高能!!
虽然图片都是100%父容器显示,但加载的图片却不一样。咦?为何会不一样呢?
其实很好理解,前者是340px
,
后者是calc(100vw - 20px)
,一个是定值,一个动态的。前者永远是340w规格,而后者在尺寸是250像素时候,实际像素是230px
,
可以看成230w
,比256w
小,于是就加载了256这种图片啦!
因此,如果大家希望图片的加载进一步智能,建议使用动态单位。