Viewport学习记录

在开发移动端项目时,以前都只知道在head中添加以下代码就可以使得在web的页面在移动端也显示的相对好看点,但具体不是很清楚原理。
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />
最近项目上写了一个移动端的小项目,为了兼容移动端的样式,使用了手淘的flexible.js,rem单位取代px。
rem我知道是以根元素(html)的字体宽度作为基准进行计算。
参考了以下两篇博文:
viewport探索 flexible.js解读
移动端高清、多屏适配方案

物理像素、独立像素、设备像素比

屏幕通常由很多像素点构成,我们经常说的分辨,例如19201080,就是指屏幕有1920\1080个像素构成,是最小的单位,也是厂商定好的,无法更改。
设备的独立像素也称css像素,可以认为是将屏幕分成坐标系,每一个点代表一个css像素点,单位是px。独立像素和css像素之间的计算由相关系统计算,存在一定的对应关系。
设备像素比,定义了物理像素和css像素的关系,代表了1个css可以代表多少个物理像素点。计算公式:

设备像素比 = 物理像素 / css像素

目前,js可以通过window.devicePixelRatio获取到设备像素比,css可以使用-webkit-device-pixel-ratio(其他的内核使用对应的标志)获得并配合media query使用。

两个像素的关系

在PC上浏览器的宽度的调整并且宽度计算是通过物理像素,这使得在页面不缩放(100%)的情况下,1个css像素等于1个物理像素.放大到200%,一个css像素等于4个物理像素,css像素数减半。

1px==1px
1px==1px
100%时,1css像素大小与设备像素相等
拉伸
拉伸
放大过程,css像素被拉伸
缩小
缩小
缩小过程,css像素被缩小

viewport

浏览器中,百分比宽都是通过父元素的宽计算得到的。body的宽取自html,而html则是取自viewport,而viewport则取自浏览器窗口。viewport是用来约束顶级元素html的,它并不是一个html结构。

  • screen.width
  • winodw.innerWidth
  • document.documentElement.clientWidth
  • document.documentElement.offsetwidth

innerWidth获取浏览器可见内容区域的宽度(包含滚动条)


clientWidth获取viewport的宽(不包含滚动条)

offsetwid获取html的宽,之前说过viewport是限制html的内容区域,未修改时,html的宽都是100%继承viewport的宽。
在PC上,我们一般不会太关注这些。因为PC浏览器viewport由浏览器窗口大小决定,而移动端则会有明显的问题。

移动端的viewport

在移动端显示PC的网页,实际情况如下图,这个viewport称为布局视口(layout viewport)。而网页显示在屏幕可视区域的部分成为视觉视口(visual viewport)。



默认情况下,大多数移动端浏览器会将视觉视口这个框缩放到与布局视口相同,则会看到一下情况:

关于这两个视口的解释:

把layout viewport想像成为一张不会变更大小或者形状的大图。现在想像你有一个小一些的框架,你通过它来看这张大图。(译者:可以理解为「管中窥豹」)这个小框架的周围被不透明的材料所环绕,这掩盖了你所有的视线,只留这张大图的一部分给你。你通过这个框架所能看到的大图的部分就是visual viewport。当你保持框架(缩小)来看整个图片的时候,你可以不用管大图,或者你可以靠近一些(放大)只看局部。你也可以改变框架的方向,但是大图(layout viewport)的大小和形状永远不会变。
visual viewport是页面当前显示在屏幕上的部分。用户可以通过滚动来改变他所看到的页面的部分,或者通过缩放来改变visual viewport的大小。

在移动端,布局视口仍然是用来限制网页布局部分的视口,其大小仍然可以用clientWidth/Hieght得到。而视觉视口的大小则可以用innerWidth/height获取,并且取到的都是css像素。

######理想视口(ideal viewport)
所谓理想视口,就是在页面初始渲染好后,不经过用户缩放或拖动页面就能完美显示网页内容的视口。理想视口在不同的设备是一个不同的值,一般有设备设置,可通过这个链接查询不同机型的理想视口。

viewport meta标签

为了解决移动端视口,苹果最先引入了viewport meta以解决这个问题。属性:

width:用来设置 layout viewport 的宽度,可以设为字符串device-width。
height:和 width 相对应,指定高度。
initial-scale:初始缩放比例,也即是当页面第一次 load 的时候缩放比例。
maximum-scale:允许用户缩放到的最大比例。
minimum-scale:允许用户缩放到的最小比例。
user-scalable:用户是否可以手动缩放

因为布局视口是限制html布局的,所以只要给是布局视口设一个合适的值,视觉视口自动缩放在屏幕上就能合理的显示所有内容。我们一般设置width=device-width,浏览器会自动设置布局视口为理想视口,但还有一个initial-scale=1。
之前提到过,视觉视口会自动缩放到匹配布局视口,使得完整显示整个网页,但这样内容往往很小,需要放大才能看清。理想视口与视觉视口、缩放值之间的关系为:

visual viewport width = ideal viewport width / zoom factor

所以initial-scale=1,所做的事就是使得视觉视口、理想视口、布局视口三者保持一致。同时,由于某些安卓设备只有在initial-scale=1的情况下才会计算出视觉视口,并设置成理想视口,所有安卓设备下会手动设置为1。

缩放

设备像素比(dpr),代表的是1个css像素在某个方向上能占据的物理像素点个数。
理想视口在设备是提供的,视觉视口中的像素是相对于它缩放得到的。放大时,视觉视口的css像素变少,反之则增多。而缩放的实质也是在改变一个css像素包含的设备像素个数。
理想视口有设备提供,其宽度也就是设备的独立像素。

由以上公式可知: 视觉视口 / 理想视口 = 1 / scale

当在设置了meta viewport之后,

布局视口的宽==视觉视口的宽\==屏幕的宽

故可知:dpr == 1 / scale

知道这些基础知识后,再去看flexible.js差不多应该就会理解工作原理了。