像素单位
像素单位有设备像素、逻辑像素和CSS像素3种。
设备像素(device pixels)、设备分辨率
设备像素也叫物理像素。
设备像素指的是显示器上的真实像素,每个像素的大小是屏幕固有的属性,屏幕出厂以后就不会改变了。
设备分辨率描述的就是这个显示器的宽和高分别是多少个设备像素。
设备像素和设备分辨率交给操作系统来管理,浏览器不知道、也不需要知道设备分辨率的大小,浏览器只需要知道逻辑分辨率就可以了。
设备独立像素(Device Independent Pixels)、逻辑分辨率
设备独立像素也叫逻辑像素。
设备独立像素(dips)是操作系统定义的一种像素单位,应用程序将设备独立像素告诉操作系统,操作系统再将设备独立像素转化为设备像素,从而控制屏幕上真正的物理像素点。
为什么需要在应用程序与设备像素之间定义这么一种单位呢?为什么应用程序不应该直接使用设备像素?
随着显示器制造技术越来越先进,屏幕像素密度越来越高。同样是19201080颗像素,以前要放在宽大的显示器中,现在都可以放在手机屏幕上了。原本高度为12个设备像素的字体,现在高度为24个设备像素才能得到相近的大小(这也说明字变得更加清晰锐利了),如果应用程序直接使用设备像素,那么编写应用程序将变得非常困难:字体在一些屏幕上高度为12个设备像素,在另一些屏幕上却要变为24个设备像素。
因此操作系统定义了一个单位:设备独立像素。操作系统保证:用设备独立像素定义的尺寸,不管屏幕的参数如何,都能以合适的大小显示(这也是设备独立像素名字的由来)。操作系统是如何做到的呢?对于那些像素密度高的屏幕,将多个设备像素划分为一个逻辑像素。至于将多少设备像素划分为一个逻辑像素,这由操作系统决定*。
对于上面的例子:“原本高度为12个设备像素的字体,现在高度为24个设备像素才能得到相同的大小”,操作系统会将一个逻辑像素定义为2*2个真实像素,从而设备独立像素尺寸不需要改变,而且不管在新、旧设备上,显示的尺寸大致相同。
设备独立像素与设备像素之间的比例是多少,显示器厂商和操作系统厂商会通过调查研究来得出最利于观看的比例。普遍规律是,屏幕的像素密度越高,就需要更多的设备像素来显示一个设备独立像素。
通过screen.width/height
得到的数值就是整个屏幕(不仅仅是浏览器的区域)的宽度和高度(单位:设备独立像素)。这个数值不随页面缩放、浏览器窗口大小而改变。
逻辑分辨率用屏幕的宽*高来表示(单位:设备独立像素)。
你可以通过操作系统的分辨率设置来改变设备独立像素的大小,但在前端开发的时候我们完全可以将它们当作定值。(没人会闲着无聊频繁改变操作系统分辨率)
我屏幕的设备分辨率是1920*1200(单位:设备像素),当前的分辨率设置下逻辑分辨率是1280*800(单位:设备独立像素)。从图中可以验证,横、纵方向的设备像素数量恰好是设备独立像素的1.5倍。这也意味着,设备独立像素的边长是设备像素边长的1.5倍。
window.devicePixelRatio在下文会解释。
css像素
在CSS中使用的px
都是指css像素,比如width: 128px
。css像素的大小是很容易变化的。当我们缩放页面的时候,元素的css像素数量不会改变,改变的只是每个css像素的大小。也就是说width: 128px
的元素在缩放200%以后,宽度依然是128个css像素,只不过每个css像素的宽度和高度变为原来的两倍。如果原本元素宽度为128个设备独立像素,那么缩放200%以后元素宽度为256个设备独立像素(css像素宽度始终是128)。
开发者在开发的时候基本上只用考虑css像素,在这里介绍设备像素和设备独立像素只是为了讲述页面缩放的原理,以及方便以后理解viewport。
css像素与设备独立像素的关系
缩放比例就是css像素边长/设备独立像素边长。
在缩放比例为100%的情况下,一个css像素大小等于一个设备独立像素。
css像素与设备像素的关系
window.devicePixelRatio设备像素比,devicePixelRatio = (在相同长度的直线上)设备像素的数量 / CSS像素的数量。这个比例也等价于CSS像素边长/设备像素边长。如devicePixelRatio=2,表示在相同长度的直线上,设备像素的数量是CSS像素数量的2倍,因此CSS像素的边长是设备像素的2倍。
缩放会导致CSS像素边长的改变,从而导致window.devicePixelRatio的改变!
例子
我的屏幕宽度是1280个设备独立像素,我将div宽度设为了1280px(css像素),当缩放为100%的时候,DIV恰好撑满整个屏幕,不会出现横向滚动条。(这说明缩放比例为100%的时候一个CSS像素完全等于一个设备独立像素。)
这里有一个小坑点。如果纵向滚动条存在的话,它会占据一点点宽度,这时如果我还将元素宽度设为屏幕宽度1280px,屏幕就无法装下整个元素,然后就会出现横向滚动条。
在上面这个例子中因为纵向滚动条不存在,所以没有这个问题,将来在开发的时候要注意。
注意到我设置了5px的橙色边框,为什么最终的宽度不是1280+5+5=1290呢?因为我给所有元素加上了
box-sizing: border-box
的样式,这样我设置的边框宽度就会包含在width中,也就是最终加上边框以后宽度为1280px。
当我缩小浏览器窗口的时候滚动条出现了。因为div的宽度没有改变,无论以什么单位衡量(设备像素、设备独立像素还是CSS像素)。
因为缩放依然是100%,css像素边长/设备独立像素边长依然是1:1。
窗口最大化,当我缩放200%时,屏幕只能显示DIV的左半部分了,这时DIV的宽度依然是1280个css像素,但是它宽度变成了2560个设备独立像素。
以下是测试用的简单代码,大家可以自己在Chrome DevTools中试试!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<title>test</title>
<style>
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
text-align: center;
width: 100%;
}
#box {
background: lightblue;
width: 100%;
height: 1000px;
border-radius: 20px;
border: 5px solid orangered;
}
</style>
</head>
<body>
<div id="box">this is box<br> 1
<br> 2
<br> 3
<br> 4
<br> 5
<br> 6
<br> 7
<br> 8
<br> 9
<br> 10
<br>
</div>
</body>
</html>
参考文章:http://weizhifeng.net/viewports.html
欢迎阅读我的下一篇文章,它使用这篇文章介绍的3个概念,来解释前端开发中与尺寸有关的概念和属性。