前言

随着科技的发展,电子产品的种类越来越多,各种屏幕尺寸的大小设备层出不穷。以前前端为了单一设备,分别设置不同的尺寸,现在设备增多,这种方法已经很不容易使用,光维护数量众多的不同尺寸的图片就够麻烦。

响应式

高度自适应

所以提出了响应式图片,希望一张或是多张图片可以适应所有的设置,显示正常,多张图片,不同的图片对应不同的设备尺寸,能够完好的展示出图片的效果,最简单的响应式图片如下。

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>

picturevideo元素类似,我们需要在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>
最后修改:2019 年 02 月 24 日
如果觉得我的文章对你有用,请随意赞赏