html img 响应式,图片响应式解决方案

背景

众所周知,retina屏的设备像素比是2,而普通屏幕像素比为1,对于图片这种位图像素已定的资源,如果不加以处理的话,要么全都用1倍图,在retina屏上观看就会模糊;要么都是用2倍图,那么在普通屏幕上浏览的时候就会白白浪费流量消耗下载速度。

简单介绍下css像素和位图像素的区别:

无论是retina屏还是普通屏幕,图片展示的区域大小是相同的,这也就是css像素与设备无关。

retina屏一个1x1的css像素区域对应着2x2的物理像素,也就是每个css像素宽的区域,在retina屏上是可以再分成两半来显示的,即dpr=2的retina屏上的最小css像素分辨率是0.5px。

理论上,一个位图像素是对应一个物理像素的时候展示完美:

1、假如在retina屏使用1倍图:也就是1个位图大小的区域去用4个物理像素渲染,被分割的位图只能就近取色,就会导致图片显示模糊;

2、同样的,如果在普通屏幕上使用2x图,那么就会一个物理像素对应4个位图像素,就会通过一定算法,给该物理像素一个近似的值,(downsampling过程),图片不会模糊,但会缺失一些锐度。

目前主流方案(使用二倍图):

img{

max-width:100%;

height:auto;

}

而图片展示的情况在如今也是应用的越来越多,所以要找到两者完美匹配的方法,也就是——响应式图片。

CSS解决方案——媒体查询

最大缺点:只能用于css,所以也就限定了只有background中的图片可以使用此方法。

简介一下:

@media

only screen and (-webkit-min-device-pixel-ratio:2),

only screen and (-min-moz-device-pixel-ratio:2),//版本低于16的Firefox

only screen and (min-resolution:2dppx),

only screen and (min-resolution:192dpi){

...

}

像七牛这样专业的图片处理应用都可以根据需求生成一倍图,这样对于不同分辨率的显示器,也可以使用不同分辨率的图片。另外的不足是使用媒体查询多了不少代码,个中利弊,具体情况下再权衡吧。

resolution :定义设备的分辨率。

235ef450f5e9

resolution兼容性

dppx:也是设备像素比,和dpr一样。

dpi:(Dots Per Inch)每英寸点数。

1dppx=96dpi

【小科普:1参考像素即为从一臂之遥看解析度为96DPI的设备输出即1英寸96点)时,1点(即1/6英寸)的视角。 】

另外,在最新的以webkit为内核的浏览器中,支持支持CSS4的background-image新规范草案image-set,在移动端也勉强可以接受吧。

235ef450f5e9

image-set属性兼容性

selector {

background-image: url(no-image-set.png);

background: image-set(url(foo-lowres.png) 1x,url(foo-highres.png) 2x) center;

}

不支持image-set的浏览器会解析background-image中的背景图像;支持image-set的浏览器就会根据是否为retina屏选择相应的背景图,因此这个方案是可以实现向下兼容的。

HTML解决方案——srcset+sizes+w标识符

这是HTML5推出的属性,srcset可以根据显示器分辨率智能加载最佳显示的图片。

235ef450f5e9

srcset属性兼容性

mm-width-128px.jpg

srcset="mm-width-128px.jpg 128w, mm-width-256px.jpg 256w, mm-width-512px.jpg 512w"

sizes="(max-width: 360px) 340px, 128px">

srcset :指向提供的图片资源,为用户提供了一种内嵌简单的分辨率媒体查询功能;

sizes : 指定图片宽度,不能使用百分比,可使用:

px,

vw(100vw就是占满父容器宽度,所以要求图片居中宽度为百分比的地方可以使用vw单位,如 sizes=80vw),

calc运算(适用于两边距离固定的情况,如sizes="calc(100vw-20px)"),

媒体查询(如sizes="(min-width:360px) 340px,128px")。

而且最重要的是,sizes属性产生的初衷就是可以在html中实现简单的媒体查询功能,来适应越来越大规模的响应式网站开发。

那么w是个啥?

w是一个衡量宽度的标识符,一定要对应图片的真实宽度,这会使得浏览器正确的选择图片,如果w值和图片宽度不对应时,实际渲染是会有问题的。

拿这段代码来说:

test-240.jpg

srcset="test-240.jpg 240w, test-480.jpg 480w, test-720.jpg 720w"

sizes="240px">

sizes=240px,也就是图片宽度设置为了240px,那么:

当该屏幕dpr==1时,就会选用test-240.jpg;

235ef450f5e9

dpr==1

dpr==2时,可渲染的位图像素宽度就变为了480px,也就选用了test-480.jpg;

235ef450f5e9

dpr==2

dpr==3时,能渲染的位图像素宽度变为了720px,那么浏览器去选择最适合的图片,也就是test-720.jpg;

235ef450f5e9

dpr==3

关于w值设置如果不正确,会出现什么后果,我在这篇文章中写了详细的案例。

现代浏览器对该属性的支持是越来越多了,这个方案应该会是个潮流。

在移动端andriod browser的支持度实在是太差劲了,PC端对于一些fashion的网址试一试。

javascript解决方案

基于jquery的HiSRC插件,可以基于网速和是否为retina屏来显示图片。

200x100.png

然后调用hisrc的方法

$(document).ready(function(){

$(".hisrc img").hisrc();

})

官方文档是这样介绍HiSRC如何工作的:正常情况下会直接加载src中的资源;如果网速较好就会加载data-1x中的资源替代原来src的文件;如果设备像素比又比较高的话,就会加载data-2x中的资源代替原来的src中的图片。

它还提供选项允许我们设置一个网速基准。这个html的结构让我不由得想起了lazyload的解决方案,这俩真的是太相似了,我们完全可以给src中放一个统一的占位图,然后再去选择加载适合浏览器展示的图片。

另外还有用于rails的gem包:hisrc-rails.

所以也可以写成这样

responsive_image_tag("http://placehold.it/100x100", :'1x' => "http://placehold.it/200x200", :'2x' => "http://placehold.it/400x400")

对于这个方案,个人觉得在工程上应用是可以期待的,因为图片都放在七牛那儿,可以图片上传成功后从2倍图中处理出1倍图,然后再向img标签中添加data-1x,data-2x这样的属性,不过呢,这好像把工作几乎全部添加给了后台的哥们儿,想到这儿,好像应用的难度瞬间增大了呢。。。

picturefill方案,依赖picturefill.js这个脚本文件,并且它还对结构有一定的要求,对格式有特定的要求,最开始这个来自于对的支持。

235ef450f5e9

element兼容性

看到该结构要写这么多代码,多少就会产生一点心理抗拒,但是呢本着技术进步的态度,还是再进一步研究下。

由于picture元素是html5的新产物,兼容性上还不是特别好,要想大规模使用可以配合picturefill.js,另外现在picturefill也支持有srcset属性的img。

这里有picturefill在应用的页面中存在的一些问题 。

//主要是IE9和安卓2.3上存在一些问题,不过IE9通过hack方法也是可以挽救的。

最后,两句话介绍一下服务端解决方案:

Adaptive Images:最大缺点基于PHP和Apache。它是拦截通过服务器的图片请求来生成图片,如果图片是通过第三方的分网网络的也就用不上了。

综上

不过既然picturefill也支持srcset,那么比较srcset属性和picture元素,浏览器对srcset属性的支持是更好的。所以srcset+sizes+w的img元素配合picturefill.js效果应该会不错。只是很可惜,这样的应用案例还没有找到。不过即使picturefill.js不能完美配合srcset方案,仅仅使用srcset+sizes+w就可以应付主流现代浏览器了,重要的是,这个方案完全也是向下兼容的啊。

参考:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值