在移动浏览器中使用viewport meta标签控制布局

背景

浏览器的 viewport 是可以看到Web内容的窗口区域,通常与渲染出的页面的大小不同,这种情况下,浏览器会提供滚动条以滚动访问所有内容。

窄屏幕设备(如移动设备)在一个虚拟窗口或视口中渲染页面,这个窗口或视口通常比屏幕宽;然后缩小渲染的结果,以便在一屏内显示所有内容。然后用户可以移动、缩放以查看页面的不同区域。例如,如果移动屏幕的宽度为640px,则可能会用980px的虚拟视口渲染页面,然后缩小页面以适应640px的窗口大小。

这样做是因为许多页面没有做移动端优化,在小窗口渲染时会乱掉(或看起来乱)。所以,这种虚拟视口是一种让未做移动端优化的网站在窄屏设备上看起来更好的办法。

viewport meta 标签

但是,对于用媒体查询针对窄屏幕做了优化的页面,这种机制不大好 - 比如如果虚拟视口宽 980px,那么在 640px 或 480px 或更小宽度要起作用的媒体查询就不会触发了,浪费了这些响应式设计。

为了缓解这个问题,Apple 在 Safari iOS 中引入了“viewport meta 标签”,让Web开发人员控制视口的大小和比例。很多其他移动浏览器现在也支持此标签,但它不属于 Web 标准。 苹果的文档详尽地说明了web开发人员可以怎样使用这一标签,然而我们还是不得不仔细推敲Fennec究竟应该怎样实现它。例如,Safari的文档指出标签的内容应为”由逗号分隔的列表“,但是现有的浏览器和网页都把逗号、分号及空格混用作分隔符。

可以在A Tale of Two Viewports了解更多在不同移动浏览器中视口的情况。

视口基础

一个典型的针对移动端优化的站点包含类似下面的内容:

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

width属性控制视口的宽度。可以像width=600这样设为确切的像素数,或者设为device-width 特殊值,代表缩放为 100% 时以 CSS 像素计量的屏幕宽度。(相应的也有heightdevice-height属性,可能对包含基于视口高度调整大小及位置的元素的页面有用。)

initial-scale 属性控制页面最初加载时的缩放等级。maximum-scaleminimum-scaleuser-scalable属性控制允许用户以怎样的方式放大或缩小页面。

 使用 user-scalable=no 会导致可访问性问题,让有视觉障碍(如视力差)的用户使用困难。

像素并非像素

近年来,屏幕分辨率已经涨到人眼难以区分单个像素大小的程度。例如,最近的智能手机通常具有5英寸屏幕,分辨率高达1920-1080像素(~400dpi)。因此,许多浏览器让每个 CSS 像素对应多个硬件像素,以便在很小的物理尺寸上显示的页面能看清楚。最初这样做在许多触控优化的网站上有可用性和可读性问题, Peter-Paul Koch在A pixel is not a pixel中写到过。

在高 dpi 屏幕上,初始比例 = 1 的页面将被浏览器有效缩放。他们的文字将是流畅和清晰的,但位图图像可能无法利用全屏分辨率。为了在这些屏幕上获得更清晰的图像,Web开发人员可能希望以比其最终大小更高的比例设计图像(或整个布局),然后使用CSS或视口属性缩小它们。这与CSS 2.1标准一致:

如果显示设备的像素密度与典型的电脑显示器差异明显,用户代理应当重新调整像素值。推荐的做法是,将一个像素单位(pixel unit)对应为特定数量的设备像素(device pixel),使这个数量的设备像素所占的大小最接近参考像素的大小。而参考像素(reference pixel)的大小则推荐为阅读者在一臂远的距离观看像素密度为 96 dpi 的设备时一个像素所占的视角大小

对于Web开发人员,这意味着页面的大小远小于实际像素数,浏览器可能会相应地调整其布局和图像的大小。不过要记得不是所有移动设备的宽度都一样,你应该确保你的页面在不同屏幕尺寸和不同方向上都能很好地显示。

默认比例依赖于显示密度。在密度低于200 dpi的显示设备上,比例为1.0。在密度介于200及300 dpi之间的显示设备上,比例为1.5。对于具有300 dpi以上密度的显示设备,比例为密度除以 150 dpi 后向下取整的结果。注意,只有在视口比例为1时,默认比例才会生效。否则,CSS 像素(即像素单位)与设备像素之间的关系依赖于当前的缩放等级。

视口宽度及屏幕宽度

网站可以将其视口设置为特定大小。例如,定义 "width=320,initial-scale=1" 可在纵向的小手机屏幕上精确显示。但这样一来浏览器就不会渲染大尺寸页面,从而导致问题。为解决此问题,浏览器将根据需要扩展视口宽度,以按要求的比例填充屏幕,在iPad等大屏幕设备上尤其有用。 (Allen Pike的viewport for iPad sites对web开发者做了充分说明。)

对于设置了初始或最大缩放的页面,width属性实际上变成了最小视口宽度。比如,如果你的布局需要至少500像素的宽度,那么你可以使用以下标记。当屏幕宽度大于500像素时,浏览器会扩展视口(而不是放大页面)来适应屏幕:

<meta name="viewport" content="width=500, initial-scale=1">

可用属性还有 minimum-scale、 maximum-scale 和 user-scalable。这些属性会影响初始尺寸及宽度,并且会限制缩放等级。

移动浏览器在处理屏幕方向改变时稍有差异。例如,Mobile Safari通常在竖屏转横屏时只缩放页面,而不会把页面重新布局成横屏载入时的效果。如果web开发者想让iPhone在方向切换时保持固定比例,需要增加一个maximum-scale值来避免这样的的缩放,这会带来并非预期的禁止用户缩放页面的副作用:

<meta name="viewport" content="initial-scale=1, maximum-scale=1">

通过将初始缩放和最小缩放设置为0.86来限制一些智能手机的缩小操作。结果是水平滚动在任何方向都被抑制,用户可以根据需要放大。

<meta name="viewport" content="width=device-width, initial-scale=0.86, maximum-scale=3.0, minimum-scale=0.86">

手机平板通用的视口尺寸

如果你想知道各种手机和平板设备各有怎样的视口宽度,这里有一个手机平板视口尺寸的综合列表。它提供了一些诸如横屏及竖屏的视口宽度、物理屏幕宽度、操作系统以及像素密度的信息。

规范

Specification Status Comment
CSS Device Adaptation
<meta name="viewport">
Working Draft Non-normatively describes the Viewport META element

显然,viewport meta 标签为人们所需,因为大多数流行的浏览器均已支持这个标签,成千上万的站点也正在使用这个标签。如果有一个真正的标准让网页控制视口属性该多好。随着标准化工作逐步推进,Mozilla 会跟进任何最新的变化。