移动端适配:像素与视口

相关概念

设备像素/硬件像素/物理像素

设备像素,也称为硬件像素、物理像素,是显示屏上能够显示颜色的最小的单位,由一组物理灯(每组包括红、绿、蓝三种颜色的灯)构成,通过在不同光强下打开或关闭这些灯,可以产生任意数量的颜色和亮度。

设备的物理像素数是固定的,是厂商在出厂时就设置好了的 —— 即一个设备的(物理)分辨率是固定的。比如iPhone5的(物理)分辨率为640x1136,则设备像素数为640x1136。

逻辑像素

它表示应用程序所使用的一个抽象像素,最终会被底层系统转换为物理像素,是与屏幕像素密度无关的抽象的点的概念。一个逻辑像素在不同设备中占据相同的大小。而设备中的物理像素与逻辑像素不一定相等。逻辑像素与设备像素的关系可以根据设备像素比得出。当设备像素比为1时,1个逻辑像素等于1个设备像素。当设备像素比为n时,一个逻辑像素等于n*n个设备像素。比如iPhone5使用的是Retina视网膜屏幕,用2x2的设备像素代表1x1的逻辑像素,所以设备像素数为640x1136,而逻辑像素数为320x568。

在iOS中,逻辑像素的单位是PT(Point,显示点)。一个iOS点point等于163dpi屏幕上的一个物理像素,所以1个点pt相当于一英寸的 1/163。pt单位转换为设备像素:px = pt * (dpi / 163)

设备独立像素/密度独立像素

在Android中,逻辑像素的单位是DP/DIP(device-independent pixels/density-independent pixel)。一个设备独立像素等于160dpi屏幕上的一个物理像素,所以一个设备独立像素DP相当于1英寸的 1/160。dp单位转换为设备像素:px = dp * (dpi / 160)

CSS像素

CSS像素是Web编程的概念,指的是CSS样式代码中使用的逻辑像素单位。CSS像素是一个抽象的参考像素,CSS标准中规定96个CSS像素等于一CSS英寸。

渲染像素

当操作系统渲染屏幕时,逻辑像素会被转换为渲染像素Rendered Pixels,这一过程也被称为rasterization光栅化。逻辑像素与渲染像素的转换使用设备像素比。对于大多数设备,在物理设备的屏幕上显示渲染像素不会涉及多余的转换。此时,渲染像素的大小和物理像素的大小相等。但在某些设备中,如iPhone 6 Plus中,物理像素分辨率比渲染像素分辨率小,渲染像素和物理像素大小不等,需要对渲染像素进行转换。(DPR准确来说应该是渲染像素与逻辑像素之比,如果不考虑iPhone 6 Plus等少数设备,即默认渲染像素和物理像素大小一样,DPR就是物理像素与逻辑像素之间的比例。)

像素密度PPI/DPI

屏幕物理区域中的像素量,使用PPI(每英寸中像素数pixels per inch)或DPI(每英寸中点数dots per inch)表示。设备像素密度值越高,即每英寸中所显示像素数越多,设备屏幕上的图像越清晰。某设备的屏幕分辨率为MxN,屏幕尺寸为L英寸,则DPI=Math.sqrt(M*M+N*N)/L

“点”dot有时用来表示像素(设备像素),特别是电脑市场,由于电脑显示器如LCD或CRT是由一个个极小的点来描绘视频的,LCD屏幕在标准屏幕分辨率下,对于一个像素可认为是由显示器的一个“点”来显示,因此ppi有时所写为DPI(dots per inch,每英寸点数)。

  • iOS像素密度分布
DPI 设备
163 iPhone 2G, 3G, 3GS
326 iPhone 4, 4s, 5, 5s, 6, 6s, 7
401 iPhone 6+, 6s+, 7+
  • Android像素密度分布
DPI 范围
ldpi 小于等于120dpi
mdpi 小于等于160dpi
hdpi 小于等于240dpi
xhdpi 小于等于320dpi
xxhdpi 小于等于480dpi
xxxhdpi 小于等于640dpi

Android系统允许在ROM中指定设备的屏幕像素密度,因此计算所得的DPI不一定是系统的DPI。

设备像素比DPR

device pixel ratio是指物理像素与逻辑像素之间的比例。当这个比例为1:1时,使用1个设备像素显示1个逻辑像素。当这个比例为n:1时,使用n * n个设备像素显示1个逻辑像素。

  • iOS设备像素比
DPI 设备 DPR
163 iPhone 2G, 3G, 3GS 1
326 iPhone 4, 4s, 5, 5s, 6, 6s, 7 2
401 iPhone 6+, 6s+, 7+ 3
  • Android设备像素比
DPI 范围 DPR
ldpi 小于等于120dpi 0.75
mdpi 小于等于160dpi 1
hdpi 小于等于240dpi 1.5
xhdpi 小于等于320dpi 2
xxhdpi 小于等于480dpi 3
xxxhdpi 小于等于640dpi 4
  • CSS pixel ratio

window.devicePixelRatio属性返回当前显示设备的物理像素分辨率与CSS像素分辨率的比值。该值也可以被解释为像素大小的比例:即一个CSS像素的大小相对于一个物理像素的大小的比值。

CSS标准中devicePixelRatio的算法

  1. 如果不存在一个输出设备,直接返回1。
  2. 令CSS像素大小为在当前页面缩放比例因子和触摸缩放比例因子为1.0的情况下,一个CSS像素的大小。
  3. 令设备像素大小为当前输出设备的一个设备像素的垂直大小。
  4. 返回设备像素大小除以CSS像素大小的结果。

viewport

Layout viewport

layout viewport

布局视口,是页面布局区域,渲染引擎工作在布局视口上。布局视口用于初始时决定如何定位和渲染内容,它与缩放级别无关,其大小是不变的。

布局视口是web布局的最上层构建块,是<html>元素的父容器。如果不设置<html>元素的大小,<html>元素的大小默认为布局视口的大小。

布局视口的大小以CSS像素度量,可以通过document.documentElement.clientWidth/clientHeight获得。在桌面浏览器中,布局视口就是浏览器窗口中的可视区域。而在移动设备中,为了让所有网站显示正常,包括那些为桌面浏览器设计的网站,移动浏览器会将布局视口的宽度设置为比屏幕宽度大。

移动浏览器 布局视口宽度(CSS像素)
Safari iPhone 980px
Opera 850px
Android WebKit 800px
IE 974px

媒体查询的width是指布局视口的宽度。

visual viewport

视觉视口,表示显示在屏幕上的页面区域,也就是布局视口的可视区域。视觉视口可以看成是一架相机,拍摄目标就是布局视口这幅图。移动相机(滚动)、改变拍摄区域大小(调整浏览器窗口大小)和调整拍摄距离(改变缩放比例)都可以改变视觉视口,而布局视口是不变的。

视觉视口的大小以CSS像素度量,表示用户可见的CSS像素数,可以通过window.innerWidth/innerHeight获得。在桌面浏览器中,视觉视口就是浏览器窗口中的可视区域。而在移动设备中,为了尽可能完整的显示页面,浏览器会将视觉视口的大小设置为和布局视口相同。

用户可以通过滚动操作来调整视觉视口的位置,从而查看页面的各个部分。用户可以通过改变浏览器窗口的大小以及缩放页面来改变视觉视口的大小。改变浏览器窗口大小,会直接改变视觉视口所占的CSS像素数。缩放页面,会使CSS像素的大小改变,间接改变视觉视口所占的CSS像素数。假设页面缩放比例为100%时,视觉视口的宽度为320个CSS像素。放大页面至200%,CSS像素增大,视觉视口的宽度就变为160个CSS像素。

ideal viewport

Ideal viewport

理想视口是一个设备的最佳布局视口的抽象概念。理想视口的宽度是 设备宽度的物理像素数/设备像素比physical pixels / devicePixelRatio,可以通过screen.width获取。开发人员可以通过width=device-widthinitial-scale=1将布局视口设置为理想视口:

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

viewport元标签

移动浏览器预设的布局视口宽度让为桌面浏览器而设计的网站能够正常显示,但是对于为移动端设计的网站来说,预设的布局视口宽度会使站点显示不正常。为了使移动站点正常显示,开发人员可以使用<meta name="viewport" content="...">标签修改布局视口。各属性之间以逗号分隔,不是所有属性都受各移动浏览器支持,但是仍可以放心的使用,浏览器会忽略它所不能理解的属性。可以设置的属性有:

  • width

取值:正整数或device-width

该属性设置布局视口的宽度,以CSS像素度量。通常设置为device-width,该值表示缩放比例为100%时屏幕宽度的CSS像素数。

  • height

取值:正整数或device-height

该属性设置布局视口的高度,不常用。

  • initial-scale

取值:[0.0-10.0]

该属性设置相对于理想视口的初始缩放比例。视觉视口的宽度就是初始缩放比例乘以理想视口的宽度,然后布局视口的宽度被设为视觉视口的宽度。

  • minimum-scale

取值:[0.0-10.0]

该属性设置最小缩放比例。

  • maximum-scale

取值:[0.0-10.0]

该属性设置最大缩放比例。

  • user-scalable

取值:yes或no

该属性设置是否允许用户手动缩放网页,默认值为yes。设置为no就可以禁止缩放。

  • target-densitydpi

取值:正整数 | device-dpi | high-dpi | medium-dpi | low-dpi

目前只有Android支持该属性,该属性可以控制目标设备的渲染分辨率。medium-dpi是target-densitydpi的默认值,如果我们显式定义target-densitydpi=device-dpi,那么设备就会按照设备的屏幕密度来渲染页面。将它设置为device-dpi,但这会放大或缩小CSS像素。如果正在进行独立于分辨率的样式开发,使用默认值即可,因此不需要指定这个值。

应用

视口

针对移动设备进行开发时,需要将布局视口设为理想视口。viewport元标签的设置如下:

<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no" />

像素

设计师和开发人员都应该使用逻辑像素。设计师以基准倍率1.0来设计页面,对于不同的设备,开发人员只要按照逻辑像素尺寸来开发就能达到与基准倍率近似的效果。只是对于图片,需要准备相应的2倍图、3倍图。

比如设计师以iPhone 4作为基准进行设计,iPhone 4的逻辑分辨率为320x480,假设设计图中有一个长160px(逻辑像素)的进度条,开发人员根据设计图将进度条的长设为160px(逻辑像素)。

  • 在iPhone 3中,屏幕分辨率为320x480,DPR为1,则进度条占160个物理像素,是屏幕宽度的一半。
  • 在iPhone 4中,屏幕分辨率为640x960,DPR为2,则进度条占320个物理像素,是屏幕宽度的一半。
  • 在iPhone 5中,屏幕分辨率为640x1136,DPR为2,则进度条占320个物理像素,是屏幕宽度的一半。
  • 在iPhone 6中,屏幕分辨率为750x1334,DPR为2,则进度条占320个物理像素,320/750=0.43,约为屏幕宽度的一半。

如果设计师根据物理分辨率来进行设计,开发人员需要将物理像素除以设备像素比来获得逻辑像素数。

图片

为不同的屏幕密度提供相应的图片资源,可以带来合理的加载速度以及避免图片缩放导致的模糊。

比如设计师以iPhone 4作为基准进行设计,iPhone 4的逻辑分辨率为320x480,假设设计图中有一个40px(逻辑像素)的图标,开发人员根据设计图将图标设为40px(逻辑像素)。

  • 在iPhone 3中,DPR为1,则图标占40个物理像素,绘制图标时不会失真。
  • 在iPhone 4中,DPR为2,则图标占80个物理像素,需要将图标放大,绘制图标时失真。
  • 在iPhone 5中,DPR为2,则图标占80个物理像素,需要将图标放大,绘制图标时失真。
  • 在iPhone 6中,DPR为2,则图标占80个物理像素,需要将图标放大,绘制图标时失真。

如果为所有设备都提供80px的图标,绘制时不会失真,但是对于低密度设备,高清图标的加载比较慢也浪费流量。如果为中密度的设备提供40px的图标,为高密度的设备提供80px的图标,就可以避免图标缩放带来的失真。

媒体查询

device-width

媒体查询的device-width指的是设备屏幕的宽度,以CSS像素度量,和screen.width/height的值相等。开发者可以根据设备屏幕尺寸的不同应用不同的样式规则。

示例:

@media all and (max-device-width: 360px) {
    // styles
}

width

媒体查询的width指的是布局视口的宽度,以CSS像素度量,和documentElement.clientWidth/clientHeight的值相等。

示例:

@media all and (max-width: 360px) {
    // styles
}

device-pixel-ratio

-webkit-device-pixel-ratio原本是针对苹果的视网膜设备进行开发时为了将设备像素转换成CSS像素时使用的一个媒体查询表达式特性,后来该特性在Android设备中得到了支持。在Safari开发者说明中针对这一特性,有着如下所示的定义:

-webkit-device-pixel-ratio:苹果设备中使用的特殊比例:2代表视网膜屏幕,1代表标准屏幕。在Safari 4.0以上浏览器中支持。

在Andorid设备开发者专用Web网站中,针对-webkit-device-pixel-ratio有着如下所示的定义:

在Android浏览器与WebView浏览器中,支持针对特定像素密度创建样式时所使用的-webkit-device-pixel-ratio。可指定值为0.75、1与1.5,分别代表低像素密度屏幕、中像素密度屏幕与高像素密度屏幕。

在Firefox浏览器中使用-moz-device-pixel-ratio。

resolution

resolution特性是在W3C推荐的媒体查询表达式中的一个特性,在W3C网站中的定义如下所示:

resolution媒体特性描述像素密度等输出设备的分辨率。在non-squaer pixel设备中,min-resolution关键字用于指定设备的最低像素密度,max-resolution关键字用于指定设备的最高密度,不使用min-或max-前缀的resolution关键字不与任何non-squaer pixel设备相匹配。

关于resolution所使用的单位:

虽然在媒体查询表达式标准中,resolution属性使用的单位为dpi与dpcm,但是后来在2012年8月在W3C的CSS 3的值标准中,追加了dppx单位,该单位是一种最容易理解及使用的单位。目前只有Firefox 16版以上的浏览器中支持该单位。

  • dpi(dots per inch=每英寸中的点数)
  • dpcm(dots per centimeter=每厘米中的点数)
  • dppx(dots per ‘px’ unit=1px(像素)单位中的点数)

由于在CSS标准中,定义1英寸=96像素,所以1dppx=96dpi。

参考文章

  1. 像素密度的危机
  2. 像素
  3. Device-independent pixel
  4. 此像素非彼像素
  5. devicepixelratio
  6. 移动终端开发必备知识
  7. What’s a Pixel?
  8. The Ultimate Guide To iPhone Resolutions
  9. 移动端尺寸基础知识
  10. Android逻辑像素刨根问底
  11. 两个viewport的故事
  12. 在移动浏览器中使用viewport元标签控制布局
  13. 支持多种屏幕
  14. visual viewport vs layout viewport
  15. meta
  16. Configuring the Viewport
  17. An Introduction to Meta Viewport and @viewport