移动端布局准备:物理像素和CSS像素、布局视口、视觉视口、理想视口、二倍图、多倍图 的详细介绍
物理像素和CSS像素
像素是计算机屏幕中显示特定颜色的最小区域。屏幕中的像素越多,同一范围内能看到的内容就越多。或者说,当设备尺寸相同时,像素越密集,画面就越精细。那么,当我们在 CSS 中为一个元素设置属性 width: 250px; 时,会发生什么?这个元素的宽度究竟是多少像素呢?
事实上,这里已经涉及了两种不同的像素:物理像素 和 CSS 像素。
物理像素(设备像素,device pixels)
任何设备的物理像素数量都是固定的。屏幕分辨率不一定等于物理像素,可能屏幕分辨率1个像素占据多个物理像素
CSS 像素(CSS pixels)
是 CSS 和 JS 中使用的一个抽象概念。它和物理像素之间的比例取决于屏幕的特性(是否为高密度)以及用户进行的缩放,由浏览器自行换算。在目前主流的移动设备屏幕中,每 4 个像素为一组,渲染出普通屏幕中一个像素显示区域内的图像,从而实现更为精细的显示效果。此时, 250px 的元素跨越了 500 个物理像素的宽度。如果用户进行了放大,那么一个 CSS 像素还将跨越更多的物理像素。
什么是视口?
在 PC 端,视口指的是浏览器的可视区域,其宽度和浏览器窗口的宽度保持一致。在 CSS 标准文档中,视口也被称为初始包含块,它是所有 CSS 百分比宽度推算的根源,给 CSS 布局限制了一个最大宽度。
但在移动端,你布局的视口和可见的视口是不一样的。这是因为移动端的网页窗口往往比较小,我们可能会希望一个大的网页在移动端可以完整的显示;所以在默认情况下,移动端的布局视口是大于视觉视口的。移动端浏览器通常宽度是 240px~640px,而大多数为 PC 端设计的网站宽度至少为 800px,如果仍以浏览器窗口作为视口的话,网站内容在手机上看起来会非常窄。因此,引入了三个视口概念,使得移动端中的视口与浏览器宽度不再相关联,即:布局视口(Layout Viewport)、视觉视口(Visual Viewport)和理想视口(Ideal Viewport)。
布局视口(layout viewport)
一般移动设备的浏览器都默认设置了一个 viewport 元标签,定义一个虚拟的布局视口(layout viewport),用于解决早期的页面在手机上显示的问题。iOS, Android 基本都将这个视口分辨率设置为 980px,这时不论你的屏幕分辨率为多少,网页都是相对于980px进行布局。所以 PC 上的网页基本能在手机上呈现,只不过元素看上去很小,一般默认可以通过手动缩放网页。所以我们在PC端进行布局的时候相对于980px进行布局,那么放到移动端这个页面也能完全显示。这个默认980px的视口称为布局视口。
- 布局视口的宽度/高度可以通过 document.documentElement.clientWidth / Height 获取
- 如果要设置布局视口,可以使用 HTML 中的 meta 标签:<meta name="viewport" content="width=400">
视觉视口(visual viewport)
视觉视口是用户当前看到的区域,用户可以通过缩放操作视觉视口,同时不会影响布局视口。
所以,当用户放大时,视觉视口将会变小,CSS 像素将跨越更多的物理像素。
理想视口(ideal viewport)
布局视口的默认宽度并不是一个理想的宽度,布局视口的宽度应该与理想视口的宽度一致,简单理解就是设备有多宽,我们布局的视口就多宽。于是 Apple 和其他浏览器厂商引入了理想视口的概念,它对设备而言是最理想的布局视口尺寸。显示在理想视口中的网站具有最理想的宽度,用户无需进行缩放。
理想视口的值其实就是屏幕分辨率(屏幕分辨率也不一定等于物理像素)的值,它对应的像素叫做设备逻辑像素(device independent pixel, dip)。dip 和设备的物理像素无关,一个 dip 在任意像素密度的设备屏幕上都占据相同的空间。如果用户没有进行缩放,那么一个 CSS 像素就等于一个 dip。实际上,这就是响应式布局的基础。
- 如果要设置理想视口,可以使用 HTML 中的 meta 标签:<meta name="viewport" content="width=device-width">
视口的设置
我们可以使用视口元标签(viewport meta 标签)来进行布局视口的设置。<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1">
下面是每个属性的详细说明:
属性名 | 取值 | 描述 |
---|---|---|
width | 正整数或device-width | 定义视口的宽度,单位为像素 |
height | 正整数或device-height | 定义视口的高度,单位为像素,一般不用 |
initial-scale | [0.0-10.0] | 定义初始缩放值 |
minimum-scale | [0.0-10.0] | 定义放大最大比例,它必须小于或等于maximum-scale设置 |
maximum-scale | [0.0-10.0] | 定义缩小最小比例,它必须大于或等于minimum-scale设置 |
user-scalable | yes / no | 定义是否允许用户手动缩放页面,默认值 yes |
有几点值得注意:
- viewport 标签只对移动端浏览器有效,对 PC 端浏览器是无效的
- 当缩放比例为 100% 时,dip 宽度 = CSS 像素宽度 = 理想视口的宽度 = 布局视口的宽度
- 单独设置 initial-scale 或 width 都会有兼容性问题,所以设置布局视口为理想视口的最佳方法是同时设置这两个属性
- 即使设置了 user-scalable = no,在 Android Chrome 浏览器中也可以强制启用手动缩放
一倍图、二倍图、n倍图
在PC端和早前的普通手机屏幕中 1CSS像素 就等于 1物理像素。后来出现了视网膜屏幕,Retina(视网膜屏幕)是一种显示技术,可以将把更多的物理像素点压缩至一块屏幕里,从而达到更高的分辨率,并提高屏幕显示的细腻程度。
例如:视网膜屏(Retina)显示器硬件物理像素是 2880px * 1800px。当设置屏幕分辨率为 1920px * 1200px 的时候,理想视口的宽度值是 1920px。物理像素与理想视口宽度(屏幕分辨率)的比值为1.5(2880/1920),这个比值叫做设备像素比:
设备像素比 = 物理像素宽度 / 逻辑像素宽度
- 设备像素比可以通过 window.devicePixelRatio 来获取,
- 设备像素比可以使用 CSS 中的 device-pixel-ratio 来获取。
下面是常见的设备像素比:
- 普通密度桌面显示屏:devicePixelRatio = 1
- 高密度桌面显示屏(Mac Retina):devicePixelRatio = 2
- 主流手机显示屏:devicePixelRatio = 2 or 3
在设备像素比为2的屏幕中,对于一张 100px * 100px 的图片,通过 CSS 设置其宽高:{ width:100px; height:100px; }。在普通显示屏的电脑中打开是正常的,但假设在手机或 Retina 屏中打开,按照逻辑分辨率来渲染,他们的 devicePixelRatio = 2,那么就相当于拿 4 个物理像素来描绘 1 个逻辑像素,就像马赛克一样,一种颜色占据了多个像素格,这时图片就会变得模糊。
为了解决图片模糊的问题,在ui设计时,应该把图片的长宽像素大小都在需要显示的大小的基础上 * 设备像素比。例如需要显示一张 100px*100px 的图片,那么在设计之时,应该将图片设计为 200px*200px,这时在css设置其为 100px*100px 就不会导致图像失真了。
所以在设计网页之时,会先将设计图设计为实际大小的2倍,编程设置像素的时候再将其缩小,就不会导致网页显示模糊了。那么这个设计图,就叫做二倍图。
- 对于 devicePixelRatio = 1 的设备,设计图的大小应等于实际大小,这时的设计图为一倍图;
- 对于 devicePixelRatio = n 的设备,设计图的大小应为实际大小实际大小的n倍,这时的设计图为n倍图;