阅读 1070

墙裂科普:移动端适配的基础概念

近几年移动端设备数量增长迅速,导致各种设备屏幕尺寸不一,分辨率也是不尽相同。 作为一个前端开发者,就不得不面对移动端页面适配的问题,而适配的终极目标,就是让页面能在不同尺寸,不同分辨率的移动设备上,尽可能的实现合理(我对“合理”的认识是:在保证良好的用户浏览体验的前提下,尽可能的保留页面的完整性)展示

常见的移动端适配方案主要有下面几种:

  • 固定高度,宽度自适应
  • 固定宽度,viewport 缩放
  • 宽度 rem,viewport 缩放
  • vw 方案

不论适配的方案如何多变,但都绕不开几个基础概念,只有搞清楚了基础概念,才能正确的理解适配方案的工作原理,更好的帮助我们解决实际开发中的问题。

像素

pixel

在编写桌面端 CSS 代码时我们经常会使用 px 单位,比如说 width: 200px;,设置一个元素为 200 像素宽,如果该 CSS 代码应用到移动端设备,它会产生不一样的效果(看起来元素变小了),这是因为存在两种像素。

设备像素(device pixel,dp)

设备像素(又称物理像素),即屏幕的物理像素,随着设备生产出来就固定不变了,单位是 pt。比如说 iPhone X 的分辨率是 2436pt × 1125pt,表示屏幕由 2436 行,1125 列像素点组成。

CSS 像素(css pixel,px)

CSS 像素(又称虚拟像素、设备独立像素、逻辑像素) 是 web 编程的概念,指的是 CSS 样式代码中使用的逻辑像素。px 是一个相对的单位(相对于设备像素),是图像显示的基本单元,它既不是一个确定的物理量,也不是一个点或者小方块,而是一个抽象概念。

作为一个抽象概念,CSS 像素又具有两个方面的相对性,即:

  • 在同一个设备上,一个 CSS 像素所代表的设备像素是可以变化的(缩放影响);
  • 在不同的设备之间,一个 CSS 像素所代表的设备像素是可以变化的(高密度影响);

像素密度(Pixels Per Inch,PPI)

像素密度,准确的说是每平方英寸(1 英寸等于 2.54 厘米)的面积上排列的像素点数量。像素密度越高,代表屏幕显示效果越精细。

PPI

PPI 有对应的计算公式:

ppi formula

通过下图更直观的了解计算过程:

ppi iphone

设备像素比(Device Pixels Ratio,DPR)

设备像素比指在 未缩放 情况下,设备像素 与 CSS 像素的初始比例关系。简单理解就是在移动开发中 1 个 CSS 像素占用多少设备像素:

DPR

DPR 的计算方式如下:

dpr formula

简单理解,DPR 与 PPI 呈正相关的关系,PPI 越大,则像素点排列越紧密,DPR 也就越大。

PS:JavaScript 中可以通过 window.devicePixelRatio 代码得到 DPR 的值。

分辨率

分辨率指的是整块屏幕的尺寸,与像素密度(PPI)是不同的概念,不要混淆。

脱离屏幕尺寸单说单个设备像素大小没有实际意义,因为你可以将 1920 * 1080 颗像素放到一台 40 寸的小米电视机里面,也可以将同样多的像素全部塞到一台 5.5 寸的 iPhone7 Plus 手机里面去,那么对于 40 寸的电视而言,每个像素颗粒当然会大于 5.5 寸的手机的像素。

resolution

所以对于设计师而言屏幕的分辨率没有太多的实际意义,还是得通过分辨率计算实际的像素密度(PPI)。

视口

viewport

在桌面浏览器中,视口是一个简单的概念:视口就是浏览器的可视区域,也指浏览器的宽度。

但是在移动端,情况就变得复杂了,为了提供更好的网页浏览感受,视口被分成了 布局视口(layout viewport)视觉视口(visual viewport)理想视口(ideal viewport)

布局视口

一个没有对移动端做适配的网页在手机浏览器中浏览,手机浏览器会尽可能的缩小网页让用户看到全部的内容,比如下图中的新浪新闻:

news.sina.com

这是因为浏览器厂商把视口宽度设置得很大,一般在 768px ~ 1024px 之间(一般是 980px,具体是由设备自己决定)。所以在手机上,视口宽度与手机浏览器宽度(屏幕宽度)不再有关联,而浏览器厂商定的视口被称为 布局视口

注意:布局视口我们是看不见的,并且被缩放在屏幕内。比如说如果你创建一个 320px 宽的元素,那么它在视口宽度设置为 980px 的手机浏览器中,只能占据屏幕实际大小的 1/3 左右,效果如下图所示:

news.sina.com

下图列出了一些设备上浏览器的默认视口宽度:

layout-viewport-default-width

我们可以通过 meta 视口标签设置布局视口的宽度:

<meta name="viewport" content="width=640">
复制代码

PS:JavaScript 中可以通过document.documentElement.clientWidth/height 代码获得布局视口的尺寸。

补充一点,CSS 里面的 Media Queries(媒体查询)指定的宽度就是布局视口的宽度:

@media (min-width: 700px) {} /* 700px 指的就是布局视口的宽度 */
复制代码

视觉视口

视觉视口是用户正在看到的网页区域,它和设备的屏幕一样宽,并且它的 CSS 像素的数量会随着用户缩放而改变,也就是说缩放会影响视觉视口的大小。当缩放比为 100% 时,视觉视口与设备屏幕一样宽。放大会使得视觉视口变得更小,因为屏幕上显示的 CSS 像素更小了,而缩小会让视觉视口更大,因为屏幕上的 CSS 像素更多了。

注意一点,当用户缩放时,只有视觉视口的尺寸会发生改变,布局视口不会改变。移动端的缩放不会导致 CSS 布局被重新计算(可能是出于性能的考虑)。

PS:JavaScript 中可以通过 window.innerWidth/Height 代码获得视觉视口的尺寸。

var testDom = document.getElementById('test')

testDom.innerHTML = '屏幕宽度: ' + screen.width + '<br>视觉视口: ' + window.innerWidth + '<br>布局视口: ' + document.documentElement.clientWidth

// 以下代码表示 3 秒后,页面缩放从 100% 到 200%
setTimeout(function() {
  var metaDom = document.createElement('meta')

  metaDom.setAttribute('name', 'viewport')
  metaDom.setAttribute('content', 'initial-scale=2')
  document.querySelector('head').append(metaDom)
  testDom.innerHTML = '屏幕宽度: ' + screen.width + '<br>视觉视口: ' + window.innerWidth + '<br>布局视口: ' + document.documentElement.clientWidth
}, 3000)
复制代码

理想视口

布局视口在大多数情况下对用户都是不友好的,虽然保留了网页的完整性,但是牺牲了可用性,换句话说就是 布局视口默认的宽度并不是一个理想的宽度。所以苹果引入了理想视口的概念:理想视口对设备来说最理想的布局视口尺寸

可以通过下面的代码告诉浏览器使用它的理想视口:

<meta name="viewport" content="width=device-width">
复制代码

注意:

  • 理想视口的尺寸是由浏览器厂商决定的,开发者只能使用,而且同一设备的不同浏览器可以有不同的尺寸
  • 不同设备的相同浏览器理想视口尺寸也会不同(因为屏幕宽度不同,比如手机和平板)
  • 会随着设备转向改变

PS:可以通过 screensiz 查看相关设备的理想视口尺寸。

缩放

对于缩放,首先要搞明白一点,缩放是相对于什么来缩放的。

我们知道可以通过设置 meta 视口标签的 initial-scale 来设置页面的初始缩放值,那么当我们如下设置后:

<meta name="viewport" content="initial-scale=1">
复制代码

布局视口尺寸也会被设置为理想视口尺寸,相当于变相的设置了 width=device-width。由此,我们可以得到 缩放是相对于理想视口来进行 的结论。

layout-viewport-default-width

layout-viewport-default-width

如果要把布局视口设置为理想视口,使用 width=device-widthinitial-scale=1 都可以实现,但这两者有个兼容问题,就是 iphone、ipad、IE 会横竖屏不分,全部以竖屏的高度值作为理想视口的宽度。所以最好的设置方法是都写上去,width=device-width 解决 IE 的问题,initial-scale=1 解决 iphone、ipad 的问题:

<meta name="viewport" content="width=device-width, initial-scale=1">
复制代码

缩放与设备像素、CSS 像素的关系

缩放是在放大或缩小 CSS 像素,对设备像素无影响。

比如一个宽度为 200px 的元素无论怎么放大,都是 200 个 CSS 像素,但是因为这些像素被放大了,所以 CSS 像素也就跨越了更多的设备像素。缩小则相反。

缩放与视口的关系

缩放会影响视觉视口的尺寸,但不会影响布局视口的尺寸。

手机上页面被用户放大,视觉视口缩小,布局视口不变,视觉视口内的 CSS 像素数量减少;

手机上页面被用户缩小,视觉视口放大,布局视口不变,视觉视口内的 CSS 像素数量增多;

缩放比例

比如说在 iphone 中(理想视口宽度为 320px),如果我们设置 width=device-width, initial-scale=2,此时视觉视口的宽度会变为 160px,因为我们放大了一倍,视觉视口缩小了,1px 变得跟原来的 2px 长度一样,所以放大一倍后,原来需要 320px 才能填满的宽度只需要 160px 就能填满。因此,我们可以得到一个公式:

视觉视口宽度 = 理想视口宽度 / 当前缩放比例

当前缩放比例 = 理想视口宽度 / 视觉视口宽度

禁止缩放

如果不希望用户对网页进行缩放操作,可以通过设置 user-scalable=no 来达到禁止缩放的效果。

总结

本篇文章主要介绍了移动端适配需要理解的几个基础概念,包括 像素视口缩放,以及它们之间的相互关系。只有正确理解了这些概念才能很好的掌握移动端适配的方案及各种方案的工作机制,避免知其然不知其所以然的问题。

下一篇文章我们会详细的介绍常见的四种移动端适配方案,请期待~

参考资料

关注下面的标签,发现更多相似文章
评论