前言
随着科技的发展,电子产品的种类越来越多,各种屏幕尺寸的大小设备层出不穷。以前前端为了单一设备,分别设置不同的尺寸,现在设备增多,这种方法已经很不容易使用,光维护数量众多的不同尺寸的图片就够麻烦。
响应式
高度自适应
所以提出了响应式图片,希望一张或是多张图片可以适应所有的设置,显示正常,多张图片,不同的图片对应不同的设备尺寸,能够完好的展示出图片的效果,最简单的响应式图片如下。
img.img-responsive{
max-width: 100%;/*强制该元素百分百占据父元素*/
height: auto;/*保证宽高比例不会变化*/
}
宽度为设备视口(就是你能看到的浏览器界面的大小)宽度,高度自动这样的话,图片会根据设备大小自适应显示,保持图片的宽高比,不会出现拉伸的现象,但是随之而来的问题就是,保持宽高比,在大型设备,长宽2:1的设备上,图片显示完美,到了手机上,上下留白就很难看了,所以这种方法不能解决大多数的设备问题。
srcset
使用srcset可以根据不同的设备尺寸,引用不同大小的图片,代码如下
<img src="small.jpg" srcset=" medium.jpg 600w, large.jpg 800w">
<img src="small.jpg" srcset=" medium.jpg 1x, large.jpg 2x">
srcset
比较简单,图片路径 视口宽度,当视口宽度满足600像素时,就会加载medium.jpg
,满足800像素就会加载large.jpg
,也可以根据设备像素比来加载不同的图片,这点和媒体查询有点相似。但是srcset也有它的局限性。
比如:以Chrome浏览器为例,如果浏览器支持srcset
属性,那么src
属性中的图片是永远不会生效的。虽然srcset
语法规则和媒体查询类似,并不完全相同,当浏览器加载玩宽屏情况下的图片,再使浏览器变窄,即使此时视口宽度匹配srcset
中的某条规则,浏览器也不会加载其他图片了。这个比较合理,浏览器会认为其他的小图比不上这张大图高清,大图完全可以压缩至小图的尺寸,所以没有必要发送新的网络请求。Chrome还会利用图片缓存,如果在缓存中有上次访问留下的高清图,那么此时即使从窄屏访问,也会加载高清图。
<picture>
sizes元素
开发者无法预见用户使用什么样的设备浏览该页面,也无法知道当前<img>
元素的确切大小,但是浏览器知道,使用sizes,配合srcset就可以让浏览器根据当前的实际情况,做出一系列运算,然后显示我们想要的图片。
<img sizes=“(max-width:640px) 100vw, (max-width:960px) 50vw, calc(100vw/3)”
srcset="large.jpg 1024w, medium.jpg 640w, small.jpg 320w">
注意此时出现的srcset每一张图片后面跟着的不是设备条件,而是该图片的宽度。
这段代码的意思是,如果设备视口宽度小于640px,则当前img元素图片为当前视口宽度的100%,如果大于640px小于960px,则占当前视口宽度的50%,如果大于960px,则占当前视口宽度的三分之一。
举个例子,如果此时视口宽度为900px,根据代码,图片应该占据450px,浏览器会自动选择接近450px的图片,所以加载320px的图片。考虑另一种情况,当视口宽度大于960px时,图片元素宽度变为视口的三分之一,视口在大于960px是,图片的选择宽度大于320px,此时的320px small.jpg已经不再适用了,但实际的测试情况会出现等比例拉伸的效果,这是浏览器策略决定的,浏览器认为一定程度的图片拉伸是可以接受的,或许预判更宽的medium.jpg拥有更大的文件体积应当避免下载。
<picture>元素和<source>元素
<picture>
<source media=“(max-width:640px)” srcset="small.jpg 320w">
<source media=“(max-width:960px)” srcset="medium.jpg 640w">
<source srcset="large.jpg 1024w">
<img src="default.jpg">
</picture>
picture
和video
元素类似,我们需要在picture
添加<source>
标签,再在标签中添加媒体查询,媒体查询判断不同的设备应用不同的图片。需要注意的地方是必须要加上img标签,否则是看不到任何的效果的。source
只是为picture
提供数据源,并没有可视化的能力。
结合sizes
<picture>
<source media=“(max-width:640px)” srcset="small.jpg 2x, small.jpg 1x," sizes=“calc(100vw/3)>
<source media=“(max-width:960px)” srcset="medium.jpg 2x,medium.jpg 1x," sizes=“(max-width:960px) 50vw“>
<source srcset="large.jpg 2x,large.jpg 1x" sizes=“(max-width:640px) 100vw”>
<img src="default.jpg">
</picture>
这段代码的执行逻辑,浏览器通过执行source标签的媒体查询表达式来判断使用哪一个source作为图片来源,选定之后应用sizes属性作为它所在picture的宽度,在从srcset中附带的图片信息,选择合适的图片。
横屏竖屏
<picture>
<source srcset="smaller_landscape.jpg" media="(max-width: 40em) and (orientation: landscape)">
<source srcset="smaller_portrait.jpg" media="(max-width: 40em) and (orientation: portrait)">
<source srcset="default_landscape.jpg" media="(min-width: 40em) and (orientation: landscape)">
<source srcset="default_portrait.jpg" media="(min-width: 40em) and (orientation: portrait)">
<img srcset="default_landscape.jpg" alt="My default image">
</picture>
可以判断当前设备横屏竖屏,来加载竖屏或是横屏的图片,灵活应用。
picturefill.js
还可以使用prcturefill来实现响应式图片的解决方案
链接:http://scottjehl.github.io/picturefill/
但是IE9却不能识别被包裹在 picture 标签中的 source 元素。为了解决这个问题,在 video 标签内包住你的源元素,这就会使他们在IE9中被识别
<picture>
<!--[if IE 9]><video style="display: none;"><![endif]-->
<source srcset="smaller.jpg" media="(max-width: 768px)">
<source srcset="default.jpg">
<!--[if IE 9]></video><![endif]-->
<img srcset="default.jpg" >
</picture>
3 条评论
作者的观点新颖且实用,让人在阅读中获得了新的思考和灵感。
::funny:04::
测试