HTML 5.1 新增加了 img
元素的 srcset
、 sizes
属性和 picture
元素,使得响应式图片的实现更为简单便捷,很多主流浏览器的新版本也对这些新增加的内容支持良好。
下面通过一些例子来简要说下用法,例子里用 PLACEHOLD.IT 来获取不同像素的图片。
srcset 和 sizes 属性
srcset
是一个包含一个或多个源图的源图容器,不同源图用逗号分隔,每一个源图由下面两部分组成:
1、图片 URL
2、 x
(像素比描述)或 w
(图片像素宽度描述)描述符(与图片 URL 相隔一个空格), w
描述符的加载策略是通过 sizes
属性里的声明来计算选择的
上述第2点如果没有给出,则是默认的 1x
。
以下情况是不正确的:
- 在同一个
srcset
里的不同图片出现有的用x
描述符有的用w
描述符 - 同一个图片既使用了
x
描述符也使用了w
描述符
对于不正确的情况,不同的浏览器使用不同的处理方法。
sizes
写法与 srcset
差不多,也是用逗号分隔的一个或多个 string
,每个 string
由下面两部分组成:
1、媒体查询。最后一个 string
不能有这个,作为 fallback
2、图片 size
(大小)信息。需要注意的是这里不能使用 %
来描述图片大小,如果要用百分比来表示,要使用类似于 vw
(100vw = 100%设备宽度(viewport))这样的单位来描述,其它的像是 px
、 em
等可以正常使用。
sizes
里给出的不同媒体查询选择图片大小的建议只对 w
描述符起作用,也就是说,如果 srcset
里用的是 x
描述符或根本没有定义 srcset
,这个 sizes
是没有意义的。
x 描述符
<img
srcset=“
http://placehold.it/2500 5x,
http://placehold.it/1500 3x,
http://placehold.it/1000 2x,
http://placehold.it/500 1x
"
src="http://placehold.it/500/abc"
/>
上面代码的意思就是:5像素比(现在很多安卓手机比如小米、华为的所谓高清2k屏就是5像素比以上的)的设备使用2500x2500像素的图片,3像素比的设备使用1500x1500像素的图片,2像素比的设备使用1000x1000像素的图片,1像素比(普通的笔记本电脑显示屏就是1像素比的)的设备使用500x500像素比的图片。
对于不支持 srcset
的浏览器,显示 src
的图片(这个图片是500x500像素、RGB 颜色 abc
的)。
而对于 srcset
里没有给出像素比的设备,不同浏览器的选择策略不同。比如例子中没有给出1.5像素比的设备要使用哪张图,浏览器可以选择2像素比的也可以选择1像素比的(当然也可以选择5像素比或者使用 src
的图片,但是这显然不是一个好的选择)。
w 描述符和 sizes
w
描述符可以简单理解为描述源图的像素大小(无关宽度还是高度,大部分情况下可以理解为宽度)。
<img
srcset=“
http://placehold.it/2000 2000w,
http://placehold.it/1500 1500w,
http://placehold.it/1000 1000w,
http://placehold.it/500 500w
"
sizes=“
(max-width: 500px) 500px,
(max-width: 1000px) 1000px,
(max-width: 1500px) 1500px,
2000px
"
src="http://placehold.it/500/abc"
/>
上述例子的意思是:对于 viewport 在 500px
及以下的使用 500w
的图片,以此类推,最后一个是前面的媒体查询都不符合的情况下使用 2000w
的图片。
这里如果没有相对应的 w
描述,一般选择第一个大于它的。如上述例子中如果有一个媒体查询是 700px
的,一般加载 1000w
对应的源图。(这里之所以用“一般”这个词,是因为文档里没有规定是这样的,而根据参考和我的尝试——mac Safari 10.0.1、windows Chrome 55.0、android Chrome 55.0、windows Firefox 50.1选择加载第一个大于它的,Microsoft Edge 38选择加载的是 500w
,可能是第一个小于它的也可能是最接近的——我认为一般是选择加载第一个大于它的。)
下面说一个使用百分比的例子:
<img
srcset=“
http://placehold.it/2000 2000w,
http://placehold.it/1500 1500w,
http://placehold.it/1000 1000w,
http://placehold.it/500 500w
"
sizes=“
(max-width: 500px) 100vw,
(max-width: 1000px) 80vw,
(max-width: 1500px) 50vw,
2000px
"
src="http://placehold.it/500/abc"
/>
这里图片的选择就是: viewport 宽度乘以1或0.8或0.5得到的像素来选择不同的 w
。比如 viewport 为 800px ,对应 size
80vw ,就是 800*0.8=640 像素,应该加载一个 640w
的源图,但是没有找到 640w
,这时候一般选择第一个大于 640w
的,也就是 1000w
。
对于没有给出 sizes
的,一般是按照 100vw 来选择加载图片。当然这里也是没有规定的、看浏览器的选择的。
picture 元素
picture
元素内部的 source
与 img
的关系像是相片与相框的关系,相框带有一个底图,我很有多不同尺寸(风格)相片,我试图找到第一个合适尺寸(合适风格)的相片放到相框里,如果没有找到就不放相片而用相框本身的底图,当然如果没有相框那就不能挂到墙上去,而 picture
告诉你这个相框只能在这些图片里找合适的。
picture
支持尺寸(媒体查询)和格式选择。
下面是尺寸选择的例子:
<picture>
<source media="(max-width: 500px)" srcset="http://placehold.it/500” />
<source media="(max-width: 1000px)" srcset="http://placehold.it/1000” />
<source media="(max-width: 1500px)" srcset="http://placehold.it/1500” />
<img src="http://placehold.it/500/abc” />
</picture>
每个 source
是一个选择,媒体查询对应 media
,浏览器找到一个适用的就使用对应的 srcset
里给出的图片,对于不支持 picture
元素的浏览器可以正确的加载 img
。显然,各种 img
的属性、样式什么的也都应该写在 img
里面。
下面是格式选择的例子:
<picture>
<source type="image/vnd.ms-photo" srcset="http://placehold.it/500” />
<source type="image/jp2" srcset="http://placehold.it/1000” />
<source type="image/webp" srcset="http://placehold.it/1500” />
<img src="http://placehold.it/500/abc” />
</picture>
vnd.ms-photo
、jp2
、 webp
等是一些新的图片格式,不像 png
、 jpg
等格式获得广泛支持,但它们又有很多优点,这时候要使用的话就要进行格式支持性判断,浏览器也是选择第一个支持的格式加载对应的 srcset
里给的图片,当然对 type
判断以后不管你给的是什么格式的图片都选择加载它,如果给了不符合的另外一个格式的图片也不能再加载后面可能支持的格式了。
对于 picture
有有一点要注意的是, img
的位置会影响最终加载结果。
像下面这样写:
<picture>
<img src="http://placehold.it/500/abc” />
<source media="(max-width: 500px)" srcset="http://placehold.it/500” />
<source media="(max-width: 1000px)" srcset="http://placehold.it/1000” />
<source media="(max-width: 1500px)" srcset="http://placehold.it/1500” />
</picture>
上面这个例子在我之前提到的浏览器里,我发现它们始终选择加载 img
里的 src
图片,即使 src
的图片不能用。也就是说,相框里的底图和相片的地位同等。
picture
元素也是向后兼容的,不支持该元素的浏览器相当于只看到了 img
。
参考:
HTML 文档(这个我是在 Dash for macOS 里看的)
[ISUX译]响应式图像