viewport

相关概念

设备像素 / 物理像素

设备像素(device pixel),各个显示器上显示的图像,实际上是由横纵摆放的小方格组成的,如 分辨率 1600 x 980 ,表示 x 轴方向切割为 1600 份,y 轴方向切割为 980 份,总共 1600 x 980 个小方格。

每一个方格称之为一个物理像素

CSS 像素 / 设备无关像素

CSS像素是一个抽象的单位,主要使用在浏览器上,用来精确的度量(确定)Web页面上的内容。[1]


div {
	width: 200px;
	height: 200px;
}
					
上面 表示了 宽高都为 200 像素的 div 块,写完以上 css 样式后,会由底层系统的程序将其转换为物理像素,物理像素才是我们最终看到的内容。

设备像素比

设备像素比(device pixel ratio),指的是物理像素和设备无关像素的比例:

设备像素比 = 物理像素 / 设备无关像素
标准的 PC 设备 DPR 为 1,即在 css 中写的像素和实际显示的像素是 1 比 1 的关系,但在移动端,存在 DPR 为 2 、 3 等情况,实际情况会进行转换。
比如,css 中 width 和 height 为 1px 的 div ,在 PC 端只会渲染成 1 个像素点,而在移动端(DPR 为 2)会渲染成 4 个像素点。
这也是为什么有些手机的屏幕只有巴掌大小,但设备像素宽高却接近甚至超过 PC 端,因为在 PC 端的一个像素点,在移动端可能用 4 个或者 9 个像素来显示。比如 iphoneX 和 15.6 寸的 dell 笔记本: 在 Dell 中上显示 1px 宽 1px 高的 DOM 元素,在 iphoneX 需要 3x3 个像素。

在 javascript 中查看 DPR


window.devicePixelRatio
					

例子:iphone X

iphone X 的设备像素宽度为 1125,DPR 为 3,也就是说,在 css 中,只需要给元素设置宽度 width: 375px (1125 / 3 = 375)就可以占满屏幕宽度。如果你是在手机端,可以直接浏览该 demo: vm_iphone_x.html


<meta name="viewport" content="width=device-width">
<div style="height: 400px; width: 375px; background: linear-gradient(90deg, #000, green, #000);">
					
在 chrome dev 上调试,div 占满了宽度

viewport

meta 标签 中知道,viewport 可以设置以下属性:

width & height

width 和 height 用于定义 viewport 的宽高,以宽度为例子,默认为 980,它可以设置为两种值:

html(根标签)

html 的宽高与 viewport 的宽高挂钩,实际上 html 的宽高是以 viewport 的宽高作为参照,html 的宽高等于 viewport 的宽高。使用 meta 标签写入 viewport 信息的 width,查看 html 标签,发现宽度跟 viewport 的 width 一样。

<meta name="viewport" content="width=350">
					
查看 html 标签的宽高

使用 javascript 查看宽度


var width = window.innerWidth || document.documentElement.clientWidth  || document.body.clientWidth;
					

设置固定的 width

当给 viewport 设置了固定值的 width,从 javascript 中获得的 width 值总是前面设置的 width,并且会出现以下现象。

<meta name="viewport" content="width=350">
<div style="height: 400px;width: 350px; background: linear-gradient(90deg, #000, green, #000);">
					
由于固定死了 viewport 的大小,尽管设备的宽高一直在变,但浏览器始终认为 viewport (展示给用户的界面)是固定不变的,页面会以一种缩放的形式缩放到 viewport 的大小。这种方法可以认为 只有一种设备 来访问页面,比如设置 with=600 则认为所有设备都是 600px 宽,写个 300px 宽的 div 块则无论在哪个移动设备都占一半大小宽度,但有一个问题: PC 端不适配 ,PC 端不响应 viewport 的固定宽度。

<meta name="viewport" content="width=600">
<div style="width: 300px; margin: auto; background-color: black; color: white;">hello world</div>
					

device-width

设置 width 为 device-width 表示 viewport 宽度跟随设备宽度,设备宽度多少 viewport 的宽度就是多少。对比固定值:

第一种设置 width 为 device-width ,由于宽度跟随设备,所以浏览时总是能够显示全部的页面,即使页面实际大小远大于设备宽度,也会自动缩放到合适的程度。

第二种设置 width 为固定值(2560),表示只适配某种宽度的设备,尽管设备只有 350px 宽,由于 width=2560 ,浏览器便认为设备上的 viewport 有 2560px 宽,1280px 宽的 web 页面最终呈现出来的效果也只能占据浏览器一半宽度。

注意,这里的 1280 不是说我写了样式 width: 1280px,明确写了固定宽度 1280px 的话不会受 viewport 影响,直接就是独立像素 1280px。此处指的是不写宽度的情况下块级元素的全部宽度。

initial-scale

初始缩放比例。

参考文献

[1] 大漠 走向视网膜(Retina)的Web时代 http://www.w3cplus.com/css/towards-retina-web.html
[2] amfe/lib-flexible Github https://github.com/amfe/lib-flexible