现在上网设备越来越多,各种设备的屏幕千差万别,如果只用一张图片去涵盖所有的设备,一是可能会造成某些设备上显示效果不佳,比如使用了一张低清晰度的图,而网页运行在一个高清大屏里;二是可能会浪费带宽,比如使用了一张超大图,而网页运行在小屏幕手机里。在很多情况下我们希望浏览器能根据具体的运行环境去选择最合适的图片来加载,这便是响应式图片。
一睹为快,可以克隆示例项目到本地运行查看
基于设备像素比(DPR)加载图片
设备像素比是指物理像素和逻辑像素(或CSS像素、设备独立像素)之间的比率,比如三个物理像素对应一个逻辑像素,那么设备像素比就是3:1。
不同的设备有不同的设备像素比。比如IPhone 6的DPR是2.0,Galaxy S5的DPR是3.0。设备像素比越高,显示效果就越高清,相应的对图片的分辨率要求也就更高。因此就出现了一个需求:希望高DPR的设备下载高清图,这样就不会出现模糊,低DPR的设备下载低清图,这样更节省带宽。
<img>
标签的srcset
属性并使用x
描述符可以实现这个功能:
<img src="pic.jpg" srcset="pic-hd.jpg 2x,pic-sd.jpg 3x">
上面的代码可以根据DPR的值来加载图片,pic-hd.jpg 2x
表示当DPR=2,加载pic-hd.jpg,以此类推。
基于视口宽度加载图片
视口(viewport)就是浏览器窗口,在不同设备下,视口大小往往不同。这样就有一个问题,一张图片可能在大屏上显示正常,而在小屏幕上很能只显示到一块很小的区域里面,所以在小屏幕里面根本没必要加载这么大尺寸的图。
<img>
标签的srcset
属性并使用w
描述符,再结合sizes
属性就可以实现根据视口的宽度进行加载图片:
<img src="pic-small.jpg" srcset="pic-small.jpg 200w,pic-medium.jpg 300w,pic-large.jpg 400w" sizes="(min-width: 800px) 400px,(min-width: 500px) 270px,100px" >
上面的代码可以根据视口的宽度来加载图片,pic-small.jpg 200w
表示图像的宽度为200px,w
是图像宽度描述符,你可以当成是px
来看。sizes
属性表示的是图片显示区域的预期尺寸,(min-width: 800px) 400px
表示当视口大于800px时,图片显示区域的预期宽度是400px。
当浏览器打开网页时,它会根据屏幕大小算出图片显示区域的预期大小(通过sizes
属性里的媒体查询),然后再根据图片显示区域的预期宽度选择合适图片进行加载。
其实这里影响浏览器选择的因素不止图片显示区域宽度一个,网络、DPR都会影响浏览器选择。所以,不用去猜浏览器会怎么选择,你只要在srcset
中提供不同尺寸的图片,在sizes
中提供不同视口下的图片显示区域大小的信息,剩下的事就不要管了,具体图片的选择,就交给浏览器去做吧。
注意:媒体查询条件最好从大到小按顺序写,如上面例子中,按800px>500px>0这样的顺序写,否则一些浏览器会忽略中间的媒体查询。
基于艺术设计加载图片
有时候我们希望根据视口的大小显示不同的图片,比如,在小屏幕中只显示主体部分的图片,而在大屏幕中,则可以显示其它没那么紧要的部分。
使用<picture>
标签加<source>
标签可以实现这个功能:
<picture><source media="(min-width:800px)" srcset="pic-large.jpg"><source media="(min-width:500px)" srcset="pic-medium.jpg"><img src="pic-small.jpg">
</picture>
看起来和”基于视口宽度加载图片”的形式很像,不过这里浏览器会严格按照媒体查询的执行结果来选择加载哪个图片,不考虑网络、DPR等因素。
基于浏览器对图片格式的支持情况加载图片
不同的图片格式具有不同的特点,比如webp格式,具有很高的压缩比,但是浏览器支持情况还不太好,所以我们希望能够基于浏览器对图片格式的支持情况来选择加载合适的图片。
使用带有type
属性的<source>
标签可以实现这个功能:
<picture><source srcset="hello.webp" type="image/webp"><source srcset="hello.jxr" type="image/vnd.ms-photo"><img src="hello.jpg" alt="" width="100" height="150">
</picture>
浏览器会从一个带有type
属性的<source>
标签开始检查,如果浏览器支持webp格式,就加载webp格式图片,否则检查浏览器是否支持jxr格式,如果支持,就使用jxr格式,否则,使用默认的jpg格式。
参考链接
- HTML5标准文档之嵌入内容 文章的主要内容参考至这里
- img srcset attribute 结合标准文档综合看
- MDN img docs