移动浏览器的viewport

2011-1-2

对于移动web开发,最好了解一下viewport的概念,在quirksmode.org有两篇文章详细介绍了它,A tale of two viewport(1 2),感觉非常好,本来想翻译的,但这两篇文章实在太长了,没耐性,于是抽取了其中重点讲viewport的部分,用半翻译半自己写的方式写出来,这也是为了让自己能够理解得更好一些。

其中CSS像素和设备像素的概念,还有js获取各种宽高和位置的内容都没有提及,要想了解得更清楚还是推荐看看那两篇文章。以下图片均来自quirksmode.org

桌面浏览器

先说说桌面浏览器上viewport的概念,在桌面浏览器上viewport就是浏览器内容的可视范围,它决定了<html>元素的默认宽高。举个例子:

在一个流动布局的页面上,你给侧栏设置了width:30%,放在<body>下,正常情况下你拖动浏览器,改变浏览器的大小,这个侧栏会自动调整宽度使它的宽度为浏览器宽度的30%,那么这个自动调整的过程具体是怎样的呢?

这个侧栏会获取父元素的宽度,乘以30%得到自己的宽度。那问题就变成这个侧栏的父元素<body>宽度的取值问题。一般情况下,一个块级元素的宽度会自动伸展到父元素的宽度,所以这里<body>的宽度等于<html>的宽度。那么<html>的宽度又由谁决定?理论上,如果没有给<html>指定CSS宽度,那它的宽度由viewport决定,于是这里30%的宽度就是浏览器viewport的宽度。

viewport的宽高不仅在窗口resize的时候会改变,在缩放的时候也会变化。例如:


这个页面,有一个宽度100%的nav和宽度800px的test元素,把窗口宽度调整到800px,页面上两个元素nav和test大小是一致的。对页面通过浏览器缩放放大一倍,此时viewport的css宽度缩小为400px(设备宽度不变),nav元素的css宽度也就缩小到了400px,test元素仍然是800px,比nav大了一倍。

viewport不是HTML的一部分,无法用css控制它,对桌面浏览器来说,viewport只是一个拥有浏览器可视宽高(css像素)属性的东西。

移动浏览器

移动设备比桌面设备屏幕小很多,如果把桌面浏览器viewport的概念照搬过来会出现什么后果?

假设流动布局的网站,一般给侧栏设置width:30%,那么假设移动浏览器宽高是320*480,那么这个侧栏实际拥有的宽度只有不到100px,放几个字都不够,这会让你的网站显得很糟糕,一大票在桌面浏览器结构良好的网页在移动浏览器上都会惨不忍睹。

移动浏览器的设计者就希望移动设备上网页的显示能尽可能地接近桌面浏览器,于是有了这么两个概念:visual viewport和layout viewport。

visual viewport就是浏览器当前显示的部分页面,可以通过拖动改变页面显示的部分,通过放大缩小改变visual viewport的大小。

mobile_visualviewport

layout viewport就是提供给CSS计算的viewport,相当于桌面浏览器的viewport,不同的是layout viewport跟当前浏览器可视范围无关系,浏览器怎么缩放都与它无关,它是一个给定的值。

不同设备给layout viewport定了不同的默认值,宽度上大概是:Safari 980px,Opera 850px,Android Webkit 800px,IE 974px,高度根据设备屏幕的宽高比计算。(实际上viewport的高度几乎没用,可以忽略之)

这样提供给css计算的viewport宽高就与桌面浏览器相近了,页面计算渲染出来的效果跟桌面浏览器几乎一致。页面放大缩小不会影响到layout viewport,也就是不会影响到页面渲染。

mobile_layoutviewport

在移动浏览器上,所有页面打开时默认visual viewport = layout viewport,也就是最小缩放,例如用mobile safari打开一个页面,无论页面内容如何,都会显示980px宽度的内容。

mobile_viewportzoomedout

修改layout viewport

可以通过在<head>上写<meta>标签改变浏览器的layout viewport,如果专门针对移动浏览器设计页面,那最常用的就是设置layout viewport宽度为设备宽度,或者设置initial-scale,并设置不可缩放,这样移动浏览器就始终以1:1的方式渲染显示页面,无需理会缩放,可以像桌面浏览器那样进行精确的开发。

<meta name=”viewport” content=”width=device-width, user-scalable=no”>

<meta name=”viewport” content=”initial-scale=1.0, user-scalable=no”>

高分辨率移动设备

移动浏览器的分辨率与移动设备本身的分辨率并不一定一致。现在市面上有很多高分辨率的手机,例如3.7寸的Nexus One手机分辨率达到800*480,3.5寸的iphone4分辨率达到960*640。但如果以这样实际的值提供给浏览器进行计算和渲染,那会有两个问题。

  1. 与其他移动设备差别太大,导致之前专门设计的页面无法兼容
  2. 按照这样的分辨率去设计页面时,会乱了套,例如12px的字体在普通移动设备上显示正常,但在高分辨率设备上显得太小无法分辨,必须手动把它调高N倍。

于是这些高分辨率设备没有提供真实的像素值给浏览器,而是通过比例缩放的。例如iphone4缩小2倍(480*320),Nexus缩小1.5倍(533*320),反过来说就是每个页面都默认放大X倍显示。所以以前一个针对iphone3GS以下设计的网页,在iphone4上表现完全一致,只是更精致了。

分类:技术文章 Tags:
评论

2011年1月2日 22:27

开始往移动方向发展了哈。

2011年1月2日 22:30

请教那个运行代码是怎么弄的。。

2011年1月2日 22:50

查看源码就知道啦 在底部的bang.js,我也是在网上扒来的

2011年1月3日 10:14

可以通过在上写标签改变浏览器的layout viewport,如果专门针对移动浏览器设计页面,那最常用的就是设置layout viewport宽度为设备宽度,或者设置initial-scale,并设置不可缩放,这样移动浏览器就始终以1:1的方式渲染显示页面,无需理会缩放,可以像桌面浏览器那样进行精确的开发。上写meta>标签改变浏览器的layout viewport,如果专门针对移动浏览器设计页面,那最常用的就是设置layout viewport宽度为设备宽度,或者设置initial-scale,并设置不可缩放,这样移动浏览器就始终以1:1的方式渲染显示页面,无需理会缩放,可以像桌面浏览器那样进行精确的开发。

:上面这段话是部分类容重复了两次。

2011年1月3日 10:57

@lujun 多谢指出~看来是在排版时出错了

2011年1月17日 15:51

不错,刚入门做无线前端开发。
“修改layout viewport”这段对我用处最大,嘎嘎!

2011年8月31日 15:58

例如iphone4缩小2倍(480*320)

关于这个,我在项目中使用的时候,貌似发现分辨率是 320 * 480 的。宽度没有达到 480 。

2011年9月18日 9:39

写错了~是320*480

2016年1月5日 15:34

博客干净,简洁,阅读舒适,内容充实,作者加油,我也勉励一下自己,努力。