viewport其实没那么难理解
在学习移动端布局的时候,你肯定听说过“viewport”这个词,然后去问度娘或谷歌。你会惊奇的发现,这个viewport不简单,居然有那么多兄弟——layout viewport、visual viewport、ideal viewport。这些都是什么鬼,然后就硬着头皮去发现他们的不同,找了很多资料,很想搞懂他们,最后可能是越看越懵逼,或者就豁然开朗的懂了(我是觉得自己豁然开朗的懂了,所以才写博客记录一下感想,不对之处欢迎来喷…)。虽然自己也知道,移动端开发入门没那么难,一句代码搞定—— <meta id=”viewport” name=”viewport” content=”width=device-width; initial-scale=1.0; maximum-scale=1; user-scalable=no;”> 。可是不理解viewport心里就是不爽,下面我就简单归纳一下自己的总结。
1、各种浏览器默认viewport大小
为了能在移动设备上正常显示那些传统的为桌面浏览器设计的网站,移动设备上的浏览器都会把自己默认的viewport设为980px或1024px(也可能是其它值,这个是由设备自己决定的),但带来的后果就是浏览器会出现横向滚动条,因为浏览器可视区域的宽度是比这个默认的viewport的宽度要小的。下图列出了一些设备上浏览器的默认viewport的宽度。
2、css的1px不等于设备物理像素的1px
在早先的移动设备中,屏幕像素密度都比较低,如iphone3,它的分辨率为320×480,在iphone3上,一个css像素确实是等于一个屏幕物理像素的。后来随着技术的发展,移动设备的屏幕像素密度越来越高,从iphone4开始,苹果公司便推出了所谓的Retina屏,分辨率提高了一倍,变成640×960,但屏幕尺寸却没变化,这就意味着同样大小的屏幕上,像素却多了一倍,这时,一个css像素是等于两个物理像素的。其他品牌的移动设备也是这个道理。例如安卓设备根据屏幕像素密度可分为ldpi、mdpi、hdpi、xhdpi等不同的等级,分辨率也是五花八门,安卓设备上的一个css像素相当于多少个屏幕物理像素,也因设备的不同而不同,没有一个定论。例如,在Retina屏的iphone上,devicePixelRatio的值为2,也就是说1个css像素相当于2个物理像素。
还有一个因素也会引起css中px的变化,那就是用户缩放。例如,当用户把页面放大一倍,那么css中1px所代表的物理像素也会增加一倍;反之把页面缩小一倍,css中1px所代表的物理像素也会减少一倍。
3、viewport三兄弟——layout viewport、visual viewport、ideal viewport
layout viewport由来:如果把移动设备上浏览器的可视区域设为viewport的话,某些网站就会因为viewport太窄而显示错乱(相当于resize浏览器的窗口变小了,之后div这样的block标签默认宽度auto变小了,页面就会乱),所以这些浏览器就决定默认情况下把viewport设为一个较宽的值,比如980px,这样的话即使是那些为桌面设计的网站也能在移动浏览器上正常显示了。浏览器默认的viewport叫做 layout viewport。这个layout viewport的宽度可以通过 document.documentElement.clientWidth 来获取。
visual viewport由来:layout viewport的宽度是大于浏览器可视区域的宽度的,所以我们还需要一个viewport来代表 浏览器可视区域的大小,这个viewport叫做 visual viewport。visual viewport的宽度可以通过window.innerWidth 来获取。
其实上面俩张图还是很有误导性的。看下面这张图,没设置<meta>的情况下,同时,div宽度为auto时:(人家是刚刚好塞满的,俩种viewport比例1:1)
ideal viewport由来:现在我们已经有两个viewport了:layout viewport 和 visual viewport。但浏览器觉得还不够,因为现在越来越多的网站都会为移动设备进行单独的设计,所以必须还要有一个能完美适配移动设备的viewport。所谓的完美适配指的是,首先不需要用户缩放和横向滚动条就能正常的查看网站的所有内容;第二,显示的文字的大小是合适,比如一段14px大小的文字,不会因为在一个高密度像素的屏幕里显示得太小而无法看清,理想的情况是这段14px的文字无论是在何种密度屏幕,何种分辨率下,显示出来的大小都是差不多的。当然,不只是文字,其他元素像图片什么的也是这个道理。这个viewport叫做 ideal viewport——移动设备的理想viewport。 ideal viewport并没有一个固定的尺寸,不同的设备拥有有不同的ideal viewport。iphone的ideal viewport宽度有320px、375px..安卓设备就比较复杂了,有320px的,有360px的,有384px的等等。(不可改变的)
4、meta标签的作用
移动设备默认的viewport是layout viewport,也就是那个比屏幕要宽的viewport,但在进行移动设备网站的开发时,我们需要的是ideal viewport。那么怎么才能得到ideal viewport呢?这就该轮到meta标签出场了。我们在开发移动设备的网站时,最常见的的一个动作就是把下面这个东西复制到我们的head标签中:
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
该meta标签的作用是让当前viewport的宽度等于设备的宽度,同时不允许用户手动缩放。也许允不允许用户缩放不同的网站有不同的要求,但让viewport的宽度等于设备的宽度,这个应该是大家都想要的效果,如果你不这样的设定的话,那就会使用那个比屏幕宽的默认viewport,也就是说会出现横向滚动条。
这个name为viewport的meta标签到底有哪些东西呢,又都有什么作用呢?
width | 设置layout viewport 的宽度,为一个正整数,或字符串”width-device” |
initial-scale | 设置页面的初始缩放值,为一个数字,可以带小数 |
minimum-scale | 允许用户的最小缩放值,为一个数字,可以带小数 |
maximum-scale | 允许用户的最大缩放值,为一个数字,可以带小数 |
height | 设置layout viewport 的高度,这个属性对我们并不重要,很少使用 |
user-scalable | 是否允许用户进行缩放,值为”no”或”yes”, no 代表不允许,yes代表允许 |
上面我们说了,layout viewport = document.documentElement.clientWidth、visual viewport = window.innerWidth。由于移动端没有那个17px的滚动条,所以layout viewport ≈≈≈ visual viewport.
5、关于缩放以及initial-scale的默认值
1)、initial-scale=1可以达到和width=device-width一样的效果,因为所有的scale指令都是相对于ideal viewport的。无视layout viewport设置了多少,所以maximum-scale=3意味着最大的缩放值是ideal viewport的300%。
2)、最后再来看看initial-scale、visual viewport、ideal viewport关系:
当前缩放值 = ideal viewport宽度 / visual viewport宽度
总结:
1、document.documentElement.clientWidth和window.innerWidth的概念必须搞清楚。
document.documentElement.clientWidth/Height的值为可视窗口内部大小,不包括工具栏和水平或垂直滚动条。
window.innerWidth/Height的值也是可视窗口内部大小加上滚动条宽度。
2、meta标签中,如果设置了width=device-width 也就是将layout viewport(布局视口)的宽度设置 ideal viewport(理想视口)的宽度。width=device-width和initial-scale=1指令都可以做到。
3、当前缩放值 = ideal viewport宽度 / visual viewport宽度。