在《图像和展示》一文中,我们提到了现在各种移动设备可能会拥有比 PC 更高的分辨率,例如 iPhone 6S 的分辨率为 1920 × 1080,屏幕尺寸只有 5.5 英寸,而 MacBook Pro Retina 的分辨率为 2560 × 1600,屏幕尺寸为 13.3 英寸。
按照上一篇文章的理解,当我们建设一个 980px 宽的网站时,在 iPhone 这类高分辨率、小尺寸的设备上,岂不是会显示得非常小?我们知道,实际展示出来的样式并不是这样,那么这其中到底是什么原理呢?本文试图一探究竟。
说到这个问题,不得不说说高清屏的发展。在智能手机刚刚出现的时候,并没有所谓的高清屏,例如 iPhone 3 的分辨率是 320 × 480,而 iPhone 4 的分辨率则为 640 × 960。
按照直观理解,一个 320 像素宽的网站,在 iPhone 4 上应该会缩小一半,这样很多网站将无法正常兼容 iPhone 4。显然苹果考虑到了这个问题,为了保持和旧版 iPhone 的兼容性,当 CSS 指定宽度为 320px 时,网站依旧可以铺满屏幕。这里就涉及到了两个概念,一个是 CSS 像素,一个是 devicePixelRatio。
CSS 像素是浏览器使用的抽象单位,主要用来在网页中绘制内容。我们知道,在定义好的网页中,可以通过缩放改变页面和页面元素的大小。虽然视觉上看到的元素大小发生了变化,但是它的 CSS 像素尺寸并没有因此发生变化。
与 CSS 像素相对应的是设备物理像素和设备独立像素。物理像素指的是屏幕实际拥有的像素点,设备独立像素则可以理解为设备提供给浏览器使用的逻辑像素。devicePixelRatio 表示设备物理像素与设备独立像素之间的比例。
下面是当时常见设备的设备物理像素、设备独立像素和 devicePixelRatio:
| name | phys. width | phys. height | CSS width | CSS height | pixel ratio | phys. ppi | CSS ppi |
|---|---|---|---|---|---|---|---|
| Apple iPhone 6 | 750 | 1334 | 375 | 667 | 2 | 326 | 192 |
| Apple iPhone 5 | 640 | 1136 | 320 | 568 | 2 | 326 | 192 |
| Apple iPhone 4 | 640 | 960 | 320 | 480 | 2 | 326 | 192 |
| Apple iPhone 3 | 320 | 480 | 320 | 480 | 1 | 163 | 96 |
| Apple iPod Touch | 640 | 1136 | 320 | 568 | 2 | 326 | 192 |
| LG G3 | 1440 | 2560 | 360 | 640 | 4 | 640 | 384 |
| LG Optimus G | 768 | 1280 | 384 | 640 | 2 | 318 | 192 |
| Samsung Galaxy Note 2 | 720 | 1280 | 360 | 640 | 2 | 267 | 192 |
| Samsung Galaxy Note | 800 | 1280 | 400 | 640 | 2 | 285 | 192 |
| Samsung Galaxy S5 | 1080 | 1920 | 360 | 640 | 3 | 441 | 288 |
| Samsung Galaxy S4 | 1080 | 1920 | 360 | 640 | 3 | 441 | 288 |
| Samsung Galaxy S4 mini | 540 | 960 | 360 | 640 | 1.5 | 256 | 144 |
| Samsung Galaxy S3 | 720 | 1280 | 360 | 640 | 2 | 306 | 192 |
| Samsung Galaxy S3 mini | 480 | 800 | 320 | 533 | 1.5 | 233 | 144 |
| Samsung Galaxy S2 | 480 | 800 | 320 | 533 | 1.5 | 217 | 144 |
| Samsung Galaxy S | 480 | 800 | 320 | 533 | 1.5 | 233 | 144 |
| Samsung Galaxy Nexus | 720 | 1200 | 360 | 600 | 2 | 316 | 192 |
| LG Nexus 5 | 1080 | 1920 | 360 | 640 | 3 | 445 | 288 |
| LG Nexus 4 | 768 | 1280 | 384 | 640 | 2 | 320 | 192 |
| Microsoft Lumia 1020 | 768 | 1280 | 320 | 480 | 2.4 | 332 | 220 |
| Microsoft Lumia 925 | 768 | 1280 | 320 | 480 | 2.4 | 332 | 220 |
| Microsoft Lumia 920 | 768 | 1280 | 320 | 480 | 2.4 | 332 | 220 |
| Microsoft Lumia 900 | 480 | 800 | 320 | 480 | 1.5 | 217 | 144 |
| Microsoft Lumia 830 | 720 | 1280 | 320 | 480 | 2 | 294 | 192 |
| Microsoft Lumia 620 | 480 | 800 | 320 | 480 | 1.5 | 252 | 144 |
| HTC One | 1080 | 1920 | 360 | 640 | 3 | 468 | 288 |
| HTC 8X | 720 | 1280 | 320 | 480 | 3 | 341 | 288 |
| HTC Evo 3D | 540 | 960 | 360 | 640 | 1.5 | 256 | 144 |
| Sony Xperia Z3 | 1080 | 1920 | 360 | 598 | 3 | 424 | 288 |
| Sony Xperia Z | 1080 | 1920 | 360 | 640 | 3 | 443 | 288 |
| Sony Xperia S | 720 | 1280 | 360 | 640 | 2 | 342 | 192 |
| Sony Xperia P | 540 | 960 | 360 | 640 | 1.5 | 275 | 144 |
| Blackberry Q10 | 720 | 720 | 346 | 346 | 2 | 328 | 192 |
| Blackberry Z30 | 720 | 1280 | 360 | 640 | 2 | 295 | 192 |
| Blackberry Z10 | 768 | 1280 | 384 | 640 | 2 | 355 | 192 |
| Blackberry Torch 9800 | 360 | 480 | 360 | 480 | 1 | 187 | 96 |
| ZTE Open (Firefox OS) | 480 | 720 | 320 | 480 | 1.5 | 165 | 144 |
分析到这里,似乎所有问题都结束了。但是大家忘了一点:移动设备刚开始流行时,网站普遍缺少针对移动设备特别优化的版本,那么移动设备首先要面对的问题,就是如何兼容原来的 PC 网站。
而当时 PC 版本的网站普遍都比较宽,所以移动网站又提出了一个 viewport 的概念。它主要涉及两个概念:visual viewport 和 layout viewport。
visual viewport 指设备当前可视区域的大小,以 CSS 像素为单位;而 layout viewport 则可以理解为网页进行布局时使用的页面宽度。这两个概念比较难理解,下图进行了说明。


在当时的移动设备浏览器中,浏览器通常会虚拟出一个较大的 layout viewport。也就是说,当用这些浏览器加载一个 PC 网站时,页面可能会有一部分位于当前可视区域之外,需要滑动才能查看。
当时常见设备的 layout viewport 大致如下:
| iPhone | iPad | Android Samsung | Android HTC | Chrome | Opera Presto | BlackBerry | IE | |
|---|---|---|---|---|---|---|---|---|
| Layout viewport | 980 | 980 | 980 | 980 | 980 | 980 | 1024 | 1024 |
然而,很多网站在呈现给用户时,并不希望用户通过不断滑动来查看可视区域之外的内容。
HTML5 时代提供了 meta viewport 来控制移动浏览器的布局视口,最常见的代码是:
<meta name="viewport"content="width=device-width, initial-scale=1">
表示页面布局宽度使用设备宽度,并设置初始缩放比例为 1。配合响应式 CSS,就可以让网页更好地适应不同尺寸的设备。
更多 viewport 的用法可以点击这里。
如何用Javascript获取上述各个数据
因为设备物理像素和网页的实际展示没有完全对应的关系,所以浏览器不会直接提供一个“物理像素宽度”的统一接口。
我们可以通过浏览器的 User-Agent 判断移动设备品牌和型号,从而进一步了解它的物理分辨率。
而通过:
window.screen.width
可以获取屏幕的 CSS 像素宽度;
通过:
document.documentElement.clientWidth
可以获取当前页面的布局宽度。
另外,在现代浏览器中还可以通过:
window.devicePixelRatio
获取设备像素比。
评论0
欢迎分享你的看法,也欢迎补充不同的实践经验。