viewport 到底是什么?

viewport 就是网页的容器,它决定了用多大的空间来渲染页面。

桌面端

在桌面端,屏幕足够大,viewport 的大小一般就是浏览器显示网页的那块区域的大小,即可视区大小,用document.documentElement.clientWidth (-clientHeight) 可以获取到具体尺寸。

移动端

在移动端,想要让一个桌面尺寸的网页在小屏幕上正常显示,viewport 要足够大,这样网页才有足够的空间渲染元素。在 iPhone 上,默认 viewport 宽度是 980px,这表示屏幕横向可以容纳 980 个 CSS 像素,这个宽度足够显示大部分网页了,当然,如果网页宽度超出 980px ,屏幕会出现横向滚动条。

设置 viewport 大小

在默认 viewport 设定下,小屏幕可以完整显示网页内容,但每个元素都会变得很小,看不清,需要放大页面,滑来滑去查看,体验不好。现在的大部分网页都做了响应式设计,小屏渲染时,网页布局会发生改变以适配小屏幕,如隐藏菜单,单列布局等。在这种情况下,默认的 viewport 尺寸会让响应式布局失效。比如,一个网页用了媒体查询(@media)设置屏幕宽度小于 480px 时隐藏侧边拦,由于默认的 viewport 宽度是 980px,整个网页完整显示在屏幕上,无论如何也没法小于 480px,这个媒体查询就失效了。

那么,有没有办法可以手动指定 viewport 大小呢? 有的,用 meta 标签:

<meta name="viewport" content="width=320">

把这段代码放到 HTML 的 head 里,浏览器的 viewport 宽度就变成了320px,这意味着屏幕横向可以容纳 320个 CSS 像素,在这个 viewport 里,一个 width: 50% 的侧边栏,实际宽度是 160px (320 * 50%)。

总结一下,viewport 尺寸决定了:

  1. 屏幕可以容纳多少个 CSS 像素
  2. 百分比尺寸(如 width: 100%)的计算参照

device-width

viewport 尺寸越大,意味着同样的屏幕尺寸,要显示更多的 CSS 像素,网页元素就会变得越小。在取舍之中,每个设备都存在一个最佳的 viewport 尺寸,在这个尺寸之下,显示效果最理想。device-width 就是这个魔法。

Meta 标签里的 width,可以设定成一个数值,也可以是字符串 device-width

<meta name=“viewport” content=“width=device-width”>

顾名思义,device-width 指设备屏幕的宽度,即分辨率,或者说物理像素。 iPhone 3 屏幕的物理像素是 320 × 480,屏幕横向有 320 个像素,所以 device-width 等于 320px,但在实践中,device-width 并非都等于设备的物理像素

iPhone 4 配备了 Retina 屏幕,分辨率为 640 × 960,正好是 iPhone 3 的两倍,但 iPhone 4 的 device-width 依然是 320px,并非 640px,这是因为320x480 这个尺寸在 iPhone 上的显示效果相当理想。于是,iPhone 4 就用 2个物理像素「填充」一个 CSS 像素,这正是 Retina 屏幕显示更加细腻的原因。

同样的,Google 的 Nexus One 手机,物理像素宽度是 480px ,但工程师认为 480px 太大,所以把设备 device-width 设置成了 320px。

综上,device-width 是手机厂商的一个选择,工程师选了一个适合设备显示的最佳尺寸。Web 开发者在只管使用 device-width(或device-height),就能获得最佳的 viewport。

viewport meta

viewport 这个 meta 标签,还有一些其他的属性值:

  • width: 设置 viewport 的宽度。可以是正整数,或字符串width-device
  • height:设置 viewport 的高度,可以是正整数,或字符串width-device,几乎不用这个属性
  • user-scalable:是否允许用户缩放页面,yes允许,no 不允许
  • initial-scale: 页面的初始缩放值
  • minimum-scale:允许用户缩放的最小倍数
  • maximum-scale:允许用户缩放值的最大倍数

写起来像这样:

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

其他

Peter-Paul Koch 曾发表雄文详细剖析了 viewport,他把移动设备浏览器上的 viewport 分成了 layout viewport,visual viewport,ideal viewport 三种。虽然我觉得理解 viewport 不需要分这么多类,但我最初是顺着这种思路理解了viewport 。这种详细的研究报告不可多得,有阅读快感,推荐阅读:

A tale of two viewports — part one

A tale of two viewports — part two

Meta viewport

另外,MDN 上的 viewport 文章也可以看看,帮助理解:

在移动浏览器中使用viewport元标签控制布局 - Mobile | MDN