一、viewport的概念
PC端
viewport实际上等于浏览器窗口,拥有浏览器窗口的宽度和高度,<html>元素使用viewport宽度的100%(在未手动设置html元素宽度情况下)。用document.documentElement.clientWidth
获取viewport的宽度。用document.documentElement.offsetWidth
获取<html>元素本身的尺寸
移动端
分为visual viewport、layout viewport和ideal viewport。
关于visual viewport和layout viewport两者解释请看两个viewport的故事(第二部分)文章的viewport板块。关于ideal viewport的解释请看Meta viewport (视口元信息标签)。ideal viewport大小由设备本身决定。
CSS布局,尤其是百分比宽度,是以layout viewport做为参照系来计算的。所以<html>元素在初始情况下用的是layout viewport的宽度。
当进行缩放(如果你放大,屏幕上的CSS像素会变少)的时候,visual viewport(就是页面当前显示在屏幕上的部分)的尺寸会发生变化,layout viewport的尺寸仍然跟之前的一样。(如果不这样,你的页面将会像百分比宽度被重新计算一样而经常被重新布局。)
用document.documentElement.clientWidth
计算layout viewport的宽度。
用window.innerWidth/Height
或者document.documentElement.offsetWidth
计算visual viewport的宽度
用document.documentElement.offsetWidth
计算<html> 元素的尺寸。
二、viewport meta标签
viewport meta标签用来设置layout viewport的宽度。
initial-scale=1
visual viewport width = ideal viewport width / zoom factor
设置 initial-scale这条规则实际上做了如下2件事:
1、将页面初始缩放因子设置为给定的值,根据ideal viewport,计算得到visual viewport的宽。
2、设置layout viewport的宽等于刚刚计算出来的visual viewport的宽。
注意:对于IE,会获取一个错误的ideal viewport(320x320而不是320x480),并且会将任意值都当作成1,所以在IE上initial-scale取什么值都无所谓。
initial-scale=1可以将 layout viewport的值设置为 ideal viewport的大小。IE10上横屏模式和竖屏模式的宽都是竖屏时ideal viewport宽度。
width=device-width
width规则下有一个特殊的值device-width,通过设置width=device-width可以将layout viewport(布局视口)的宽度等于 ideal viewport(理想视口)的宽。
在iphone和ipad上,无论是竖屏还是横屏,宽度都是竖屏时ideal viewport的宽度。
initial-scale=1与width=device-width
1、使用 width=device-width 和initial-scale=1两个规则,可以将 layout viewport的值设置为 ideal viewport的大小。
2、所有的缩放规则都是相对于 ideal viewport而言的,而与layout viewport多宽无关。因此maximum-scale=3的含义就是页面最多放大到 ideal viewport的3倍。
width 和 initial-scale=1
当width 和 initial-scale=1冲突时,使用宽度最大原则(横屏或竖屏模式下均是)来解决,即哪个宽度大用哪个。
三、设备像素与CSS像素之间的换算是如何产生的
每英寸像素(pixel per inch)
ppi,表示每英寸所拥有的像素(pixel)数目,数值越高,代表显示屏能够以越高的密度显示图像。ppi的计算方式可以参考维基百科每英寸像素
设备像素比(device pixel ratio)
以上计算出ppi是为了得到密度分界,获得默认缩放比例,即设备像素比。
上图可知,ppi在120-160之间的手机被归为低密度手机,160-240被归为中密度,240-320被归为高密度,320以上被归为超高密度(Apple给了它一个高大上的名字——Retina)。
获得设备像素比后,便可得知设备像素与CSS像素之间的比例。当这个比率为1:1时,使用1个设备像素显示1个CSS像素。当这个比率为2:1时,使用4个设备像素显示1个CSS像素,当这个比率为3:1时,使用9(3*3)个设备像素显示1个CSS像素。
四、缩放实质
现代浏览器中实现缩放的方式无怪乎都是「拉伸」像素。
假设你给一个元素设置了width: 128px的属性,并且你的显示器是1024px宽,当你最大化你的浏览器屏幕,这个元素将会在你的显示器上重复显示8次(大概是这样;我们先忽略那些微妙的地方)。
如果用户进行缩放,那么计算方式将会发生变化。如果用户放大到200%,那么你的那个拥有width: 128px属性的元素在1024px宽的显示器上只会重复显示4次。元素的宽度并没有从128被修改为256像素,元素仍然是128个CSS像素宽,即使它占据了256个设备像素的空间。
参考自:
两个viewport的故事(第一部分)
两个viewport的故事(第二部分)
Meta viewport (视口元信息标签)