什么是viewport

移动端设备终端五花八门,设备尺寸、分辨率碎片化,又分普通屏幕和高清屏幕,那么如何最大程度的还原设计稿效果,就是需要解决的移动端适配问题。要解决适配问题,首先要先了解视口(viewport)这个概念。

像素概念

先说几个概念:

  • 设备像素(device pixel): 物理像素,如iPhone6的设备像素(物理分辨率)为750x1334;
  • 设备独立像素(density-independent pixel):为了兼容以前的web app提出的一个兼容概念,类似于一个中间层,如在iPhone6上,设备独立像素是375x667,一个dip其实相当于4个设备物理像素(2x2);
  • CSS像素(CSS pixels): 用于页面布局的单位,由viewport控制。样式的像素尺寸(例如width: 100px)是以CSS像素为单位指定的。CSS像素与设备独立像素的比例即为网页的缩放级别;
  • 设备像素比(device pixel ratio): 物理像素 / 设备独立像素,在javascript中,可以通过window.devicePixelRatio获取到当前设备的dpr。

视口(viewport)

那么viewport到底是什么?

桌面浏览器中,浏览器窗口就是约束你的CSS布局视口(又称初始包含块initial containing block)。它是所有CSS百分比宽度推算的根源

假设我们原来为PC开发的网页,布局用fluid布局,左边有个导航栏div,宽度是20%,div的父级元素body没有定义宽度,那么它就继续往上寻找,此时html元素也没有显式的定义宽度,如果此时浏览器宽度是1000px宽,那么左导航就是200px。

但到了手机浏览器里,移动设备的分辨率要小得多,假设是320px宽,完蛋了!左导航只有64px了,12px的文字只能显示五六个。

layout viewport

为了解决这种问题,Apple在移动版(iOS)的Safari中定义了layout viewport的概念,它的作用就是创建一个虚拟的窗口,而且这个虚拟窗口的分辨率接近于桌面显示器,Apple将其定位为980px宽。在375宽度的iPhone上,而布局视口(layout viewport)用来配合CSS渲染布局,例如当我们设置一个容器的宽度为100%时,这个容器的实际值为980px而不是375px。如此一来大部分网页就能以缩放的形式正常的显示在手机屏幕上了。

visual viewport

视觉窗口(visual viewport)就是用户当前能看到的区域,我们可以拖动横向竖向滑动条或者放大缩小网页,来达到最佳的浏览效果(类似桌面浏览器)。

ideal viewport

显然如果页面按照固定的layout viewport来布局,完全忽视了设备的差异,用户往往需要缩放和拖动来浏览网页,体验是非常差的。PPK的文章中引入了理想视口(ideal viewport)的概念。

通常我们用:

1
<meta name="viewport" content="width=device-width">

来定义理想视口,这个声明告诉浏览器,布局视口(layout viewport)的宽度和设备宽度保持一致(这样就不用缩放或滚动网页了)。

viewport定义

<meta name="viewport" content="name=value,name=value">

name/value可包含width,initial-scale,minimum-scale,maximum-scaleuser-scalable等,我们主要看以下两个:

  • width: 设置layout viewport的宽度,可以是具体的值或者device-width。
  • initial-scale: 设置页面的缩放级别和layout viewport的宽度。

初始缩放(initial-scale)

这里注意initial-scale的值是相对于理想视口(ideal viewport)的,所以initial-scale=1理论上和width=device-width可起到一样的效果。

1
visual viewport width = ideal viewport width / zoom factor

举个例子:

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

在iPhone6上渲染时,由于initial-scale=0.5同时定义了缩放级别和layout viewport,初始的

layout viewport width = 375(iphone6的理想视口是375) / 0.5 = 750

visual viewport width = 375 / 0.5 = 750

适配方案

目前最理想的适配方案是用rem来做布局,动态调整scale。参见手淘的方案hotcss

参考

  1. PPK的, ,这三篇文章,国内有热心人翻译
  2. 移动端适配方案