设计师需要知道的前端小知识1——图片为什么会模糊?
有时候,设计师输出的图片分辨率、尺寸都很高,但是在线上显示效果会模糊,这是为什么那?本文带大家了解线上图片模糊的原理
前端开发过程中,经常会遇到logo或者banner糊掉的情况,这是一个很常见,却又非常容易忽视,同时对前端交付物的用户体验影响却又相当大的一个问题。那么图片为什么会模糊?今天我们就来深入探究一下其背后的深层次原因。
一个经验性的思考:一个小图,在放大之后会模糊,很自然地我们会想:模糊的原因是因为小图放大之后像素数不够了,因此产生了模糊。然而这却无法解释,为什么有的时候明明一个很大的图片,在缩小之后,却也会模糊。显然:像素数不够,并不是决定图片是否模糊的根本原因。
在开始了解原因之前,我们首先来看一个例子:

https://youyi.asia/demos/img-clarity/(点击链接更直观观察清晰度区别)
在这个页面上有六个图片,你可以先看一下,哪张图片是最清晰的呢?
你所看到的结果和你显示器的DPR有关(Retina显示屏第一行中间的图片是模糊的,普通显示屏是清晰的,后面会讲到原因)。但不管什么屏幕,中间的图片都要比两边的清晰。中间图片的css宽度是200px,左边是199,右边是201。宽度增加1像素或者减小1像素,都会产生模糊。这是为什么呢?
一个简单的解释是:
图片的物理像素如果不能同设备的物理像素之间一一对应上,比如200px的图片被设置为199px,那么此时每个屏幕物理像素上,就需要呈现200/199≈1.005个图片像素点。也就是说,图片的1个物理像素被切割开了,然后分散在不同的物理像素上去。这时模糊就产生了。
这是比较通俗的解释。而如果想要解释背后的深层原因,我们首先需要了解几个基本概念:
图片物理像素,屏幕物理像素,css像素,屏幕PPI(DPI),Retina(视网膜)显示屏,屏幕DPR。
1.图片物理像素
图片物理像素指一个图片文件本身的尺寸,在这个图片创建的那一刻就已经确定,这个值固定不变。
后面为了方便说明,图示中用圆圈表示1个像素;![]()
2.屏幕物理像素
屏幕物理像素指一个屏幕在硬件上的像素数量,这也是一个绝对数量,固定不变。
3.css像素
css像素指我们通过css长度单位设置的像素数,比如:
.img{
width: 100px;
}
通常情况下,它是一个绝对单位,在不同屏幕上显示距离一致(这里说通常情况,是因为css像素受屏幕缩放和viewport影响)。
css像素在不同PPI或DPR屏幕上,对应不同数量的屏幕物理像素。至于1个css像素由几个屏幕物理像素呈现,由屏幕DPR参数决定。
后面为了方便说明,图示中用虚线框表示;![]()
4.屏幕DPR
DPR:Device Pixel Ratio,屏幕像素比。
DPR表示了在一个屏幕上,1px的css像素应该由多少物理像素来呈现。DPR通常和PPI相关。在传统屏幕上,这个值为1,也就是说,1个css像素对应1个物理像素;而在视网膜屏幕上,这个值为2(一个css像素对应4个物理像素)。
当DRP等于2的时候,我们称这个屏幕为“二倍屏”。
有条件的同学此时可以按F12打开控制台,在 console 中输入 window.devicePixelRatio 即可查看当前设备的DPR值。

5.屏幕PPI
PPI: Pixels Per Inch,每英寸面积上的像素数(像素密度)。
这个概念非常关键。PPI指每英寸屏幕上的像素数量。它决定了屏幕上每个物理像素点的大小。PPI越大,表示单位面积物理像素越多,单个物理像素就越小,因此显示出来的图像就更为细腻。

传统设备的PPI通常为96,部分更低的设备可能为76,通常是一些型号较为古老或者低端的显示器。此种设备如果近距离观察可以看到肉眼可见的物理像素。
当设备PPI超过300,在距离25cm左右的距离观察时,肉眼将感受不到单个的物理像素存在。
通常我们会认为:“分辨率”直接决定了屏幕显示的清晰度,这其实是一个误区,或者说是一个不严谨的表述。因为我们在这样说的时候是假定了一个“在屏幕大小确定”的前提下。事实上,PPI是影响一个屏幕显示细腻程度的决定性指标。
注:部分文章会使用DPI的概念,这里的D表示Dots,点数。在用于屏幕的上下文中,这两者表达的意思一致。DPI还可以用来表示打印设备的细腻程度。
6.Retina(视网膜)显示屏
苹果公司定义:如果显示屏PPI超过200,平板超过220,手机超过300,即可称之为Retina显示屏。
之所以数值标准不同是考虑到了在使用不同设备时人们眼睛距离设备的距离不同(更近的距离需要更细腻的屏幕像素才不至于肉眼可见,因此需要更高的PPI)。
更详细的表述
在了解了以上概念之后,一个严谨而通俗的表述就相对简单了:
我们可以想象一下:假设图片上的每一个物理像素都是一个个的鸡蛋;而屏幕上的一个个物理像素则是一个个盛放鸡蛋的“格子”,而css像素的大小,则决定了鸡蛋是“一一对应”放进去,而是要“切割”之后放进去。
一倍屏的情况
以最简单的一倍屏来举例。在普通一倍屏幕上,由DPR的知识我们知道:一个css像素对应一个物理像素。那么此时假如一个10px的图片,css宽度也为10px,那么将由10个物理像素(严谨的表述应该是“宽度”上的10个物理像素单位,为了表述方便,下文没有特别说明都指宽度上的像素数量)来呈现。这种情况,一个萝卜一个坑,互不干扰,图片是清晰的。

但假如此时我们改变css宽度,比如设置为9px,那么此时能够给我们使用的物理像素就只有9个,也就是说要把“10个鸡蛋放入9个格子中”,那么势必会出现“切割”的情况:一个格子中需要存放10/9≈1.111个,也就是多于1个的鸡蛋。

此时第一个鸡蛋将被压缩放入第一个格子,而第二个鸡蛋将被切成两部分,一部分放入第一个格子空余的位置,另一部分将放入第二个格子,以此类推。而我们知道,物理像素是组成屏幕显示的基本单位,单个物理像素上无法再显示多于一种颜色。这样一来,每个格子中的两个鸡蛋将会根据一定算法(可通过image-rendering属性指定)进行融合,原始颜色信息将被丢弃,于是模糊便产生了。
而宽度设置为11px也是同样的道理。
二倍屏的情况
在二倍屏幕上,情况稍微有点不同。二倍屏幕DPR为2,由DPR的知识我们得出:5px的css像素,将由10个物理像素去呈现。那么一个5px物理宽度的图片,在css宽度也设置5px的情况下,将对应10个物理像素,每一个“鸡蛋”将被分散放置在两个“格子”里。那么同上,模糊也就产生了。这也就是我们为什么要使用二倍图的原因。
在使用二倍图的情况下,图片物理宽度是10px,css宽度设置为5px,物理像素仍然为10个,此时恰好可以把每个“鸡蛋”放入每一个“格子”中。
同样的,如果此时我们将css像素设置为4px、6px,也会由于“割裂”而产生模糊。
总结:如何避免出现图片模糊的方法
图片模糊不是由于太大或者太小,而是取决于像素点是否被“割裂”。
因此我们的最佳实践是:


















































































