前端:移动开发 - 像素、viewport

知识

CSS 像素、物理像素、PPI

CSS 像素

CSS 像素 是 Web 编程的概念,本质上是为我们 Web 开发者创建的一个抽象结构,是相对的而不是绝对的。

物理像素

物理像素 是物理概念,屏幕是由很多像素点组成的,各像素点通过发出不同颜色的光来呈现屏幕的色彩。它是物理的,随着设备生产出来就已经被确定下来了,比如 iPhone4 的屏幕分辨率为 640×960,就表示屏幕的横向有 640 个像素点,纵向有 960 个像素点。

PPI

PPI(Pixels Per Inch)表示单位面积上的物理像素点数目。分辨率可以表示屏幕包含的像素数目,但要想描述屏幕的显示质量,还需要知道屏幕尺寸,最后算出单位面积上的像素点数目。显然 PPI 越高,屏幕显示效果越细腻。

想要解释 CSS 像素物理像素 的关系也很简单,想想 PC 浏览器网页上的缩放。如果用户进行放大操作,一个拥有 width: 300px 的元素将会占有屏幕越来越多的空间,以设备(物理)像素进行度量的话就会变得越来越宽。但对于 CSS 像素来说,无论怎样,宽度的值还是 300px,缩放效果是通过尽可能的对 CSS 像素进行拉伸来实现的。

平时电脑屏幕的 1px CSS 像素对应 1px 物理像素,所以感觉不到两者的区别,会让你误以为CSS 里的 px 就是实际屏幕像素。而真实情况是:

  • 当缩放比例为 100% 时(不缩放),1px CSS 像素对应屏幕物理像素 1px;

  • 当缩放比例大于 100% 时(放大),1px CSS 像素对应大于 1px 的屏幕物理像素;

  • 当缩放比例小于 100% 时(缩小),1px CSS 像素对应小于 1px 的屏幕物理像素。

下来的两幅图说明了当用户缩放的时候会发生什么。第一幅图展示的是当用户进行缩小操作的时候设备像素(深蓝色背景)和 CSS 像素(半透明前景)的样子。CSS 像素变得小了;一个设备像素覆盖了多个 CSS 像素。第二幅图展示的当用户进行放大操作时候设备像素和CSS像素的样子。一个CSS 像素现在覆盖了多个设备像素。(图左:放大网页,图右:缩小网页)

csspixels_in_out

逻辑像素、设备像素比

过去 iPhone 3gs 分辨率是 320x480,和平时电脑屏幕一样,1px CSS 像素对应 1px 物理像素,开发者开发网页时只要写上 CSS 像素 width:320px, height:480px 即可。但是,面对同样屏幕尺寸的 iPhone 4/4s,分辨率提升到 640x960,难道要另外为它写一份网页文档设置 CSS 像素 width:640px, height:960px 来适配高分辨率吗,显然这是不实际的。如果继续使用旧的网页文件,在高分辨率的设备上,就会显得很小,比如在分辨率为 320×480 的 iPhone 3GS 上,要画一条长度 1 英寸的线条,假设需要 163 个物理像素,即 CSS像素设成 163 像素即可;但是在分辨率为 640×960 的 iPhone4/4s 上,163 个 CSS 像素所在手机表示实际长度只有 iPhone3GS 的一半,即 0.5 英寸。如果照这种方式显示,3GS 上刚刚好的效果,在 4/4s 上就会小到根本看不清了。

但是在现实中,这两台手机显示的效果却是一样的!这是因为 Retina 屏幕把 2x2 个像素当 1 个像素使用。比如原本 44 像素高的顶部导航栏,在 Retina 屏上用了 88 个像素的高度来显示。如下图:

css-physical-pixels

逻辑像素

这里提出逻辑像素的概念。苹果使用了一套逻辑坐标系统来解决多分辨率屏幕适配问题,
例如:4/4s 的逻辑像素设为 320x480 points ,即物理屏幕上左上角为原点,横向为 X 轴 320 points,纵向为 Y 轴 480 points,名为 point(即pt)单位就是上图中的深灰色部分,显然,PPI 越高的屏幕,1 point 覆盖的物理像素就越多。Android 平台也定义了逻辑像素单位,为device-independent pixel 即 dip 或 dp。说实话,两者其实是一回事。

设备像素比

设备像素比(devicePixelRatio)= 物理像素 / dp或pt。例如:
iPhone 4/4s 设备像素比:640 / 320 = 2

单位之间的换算关系:

1倍:1pt=1dp=1px(iPhone 3GS)
2倍:1pt=1dp=2px(iPhone 4s/5/6)
3倍:1pt=1dp=3px(iPhone 6 plus)

应用

CSS 和 图片

对于开发者,实际应用中应该根据屏幕尺寸和 设备像素比(devicePixelRatio)来反推 CSS pixel。

也就是说:假设设备像素比为 2,设计图要做成了 720x1280 的,那么 CSS 里所有尺寸都除以 2 即可。

而对于图片,比如一张实际大小 100x100px 的图片,并且 width 和 height 都设了 100px(注意这里的 px 是 css pixel),实际占用了屏幕的像素数就是(假设设备像素比是 3)300x300px(注意这里的 px 是真实的屏幕像素),也就是说,变模糊了。所以,如果希望网页的元素在高 PPI 设备上显示不模糊(比如 1080x1920 屏幕的手机),位图应该做 3 倍的尺寸(比如做 300x300px 的图,然后在 CSS 中设 width 和 height 为 100px),svg(矢量图)就无所谓了。

媒体查询

注意这里的 px 是指逻辑像素,即 CSS 文件中的 width、height。
max-widthmax-device-width 都可以使用。

@media all and (max-device-width: 320px) {}

Viewport

别以为当我们为了适配手机端的问题,而特意根据屏幕尺寸和 devicePixelRatio 来反推 CSS pixel,就可以在手机端上优雅地显示网页了,手机浏览器又涉及到有关 viewport 的概念。这里介绍一下 layout viewport 和 visual viewport。

  • Layout viewport - 渲染视图,渲染页面所需要的尺寸

  • Visual viewport - 视觉视图,浏览器可视区域尺寸

Layout viewport

移动设备上的浏览器认为自己必须能让所有的网站都正常显示,即使是那些不是为移动设备设计的网站。但如果以浏览器的可视区域作为 viewport 的话,因为移动设备的屏幕都不是很宽,所以那些为桌面浏览器设计的网站放到移动设备上显示时,必然会因为移动设备的 viewport 太窄,而挤作一团,甚至布局什么的都会乱掉。所以这些浏览器就决定默认情况下把 viewport 设为一个较宽的值,比如 980px,这样的话即使是那些为桌面设计的网站也能在移动浏览器上正常显示了。ppk 把这个浏览器默认的 viewport 叫做 layout viewport。

Visual viewport

layout viewport 的宽度是大于浏览器可视区域的宽度的,所以我们还需要一个 viewport 来代表浏览器可视区域的大小,ppk 把这个 viewport 叫做 visual viewport。

图一:布局挤在小小的屏幕中; 图二:Layout viewport 和 Visual viewport

viewport

拿 iPhone 举例。
iPhone 创建出了一个 980px 的虚拟窗口——布局窗口(layout viewport)来对页面布局,这时传统的桌面端网页终于能正常布局了(虽然要放大才能看清),但正是这个 layout viewport 导致专门根据屏幕尺寸和 devicePixelRatio 优化过的页面也只能以缩放的方式显示(可以想象在你的 PC 浏览器宽 980px 窗口里打开一个 320px 的页面的情景...),那么为了让为移动设备优化过的网页正常显示,就要改变这个 layout viewport。

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

布局窗口定义为:宽度为设备宽度,初始缩放比例为 1 倍,禁止用户缩放。

参考

阅读 2.9k

推荐阅读
Teraflopst
用户专栏

我的专栏

7 人关注
18 篇文章
专栏主页