移动端像素及视口的理解
聊聊移动端的适配
H5开发相对于PC端web的开发,可以不用兼容那么多浏览器了,但是需要适配各种屏幕尺寸的适配。
先了解一下基础知识~
基本概念
1、物理像素(设备像素)
红蓝绿可以调配出任何颜色,通常说的手机像素就是由许多红蓝绿组成的一个小块,1个小块表示1个像素。一个物理像素是显示器(手机屏幕)上最小的物理显示单元,通过控制每个像素点的颜色,使屏幕显示出不同的图像。屏幕从工厂出来那天起,它上面的物理像素点就固定不变了,单位pt - 固定单位。
image.png比如:iPhone6、7、8的分辨率为 1334*750像素表示,横向750个像素,纵向1334个像素
image.png
网址:https://www.paintcodeapp.com/news/ultimate-guide-to-iphone-resolutions
2、CSS像素
CSS和JS使用的抽象单位,浏览器内的一切长度都是以CSS像素为单位的,CSS像素的单位是px。
注意:px是一个相对单位,相对的是设备像素(device pixel)。
结合上面的屋里像素的概念来理解:
一倍屏、二倍屏(Retina)、三倍屏,指的是设备以多少物理像素来显示一个CSS像素,一倍屏(普通屏幕)就是1一个CSS像素 == 1个物理像素。而多倍屏以更多更精细的物理像素点来显示一个CSS像素点,而在Retina屏幕下,1个CSS像素则等于4个物理像素,2个css像素 = 16个物理像素。
image.png
3、设备像素比(dpr)
设备像素比简称为dpr。
可以通过通过:window.devicePixelRatio获得。看图说话:
image.png- 一倍屏:当设备像素比为1:1时,使用1(1×1)个设备像素显示1个CSS像素;
- 二倍屏:当设备像素比为2:1时,使用4(2×2)个设备像素显示1个CSS像素;
- 三倍屏:当设备像素比为3:1时,使用9(3×3)个设备像素显示1个CSS像素。
4、设备独立像素:
(Device Independent Pixel) 与设备无关的逻辑像素,代表可以通过程序控制使用的虚拟像素,是一个总体概念,包括了CSS像素。
设备独立像素,也称为逻辑像素,简称dip。根据设备像素与CSS像素之间的关系、及DPR的官方定义,可以推断出:
CSS像素 =设备独立像素 = 逻辑像素
5、像素密度(PPI)
每英寸像素取值,也就是衡量单位物理面积内拥有像素值的情况。
iPhone8 PPI:
ppi越高,每英寸像素点越多,图像越清晰;我们可以类比物体的密度,密度越大,单位体积的质量就越大,ppi越高,单位面积的像素越多。
ppi在120-160之间的手机被归为低密度手机,160-240被归为中密度,240-320被归为高密度,320以上被归为超高密度(例如:苹果的Retina屏幕)
6、视口(viewport)
viewport严格等于浏览器的窗口
viewport严格等于浏览器的窗口。
话说,有个叫ppk大神对于移动设备上的viewport有着非常多的研究(第一篇,第二篇,第三篇),有兴趣的同学可以去看一下。根据ppk的观点:移动设备上有三个viewport。
- layout viewport -- 布局视口
- visual viewport -- 视觉视口
- ideal viewport -- 理想视口
怎样来理解这三个viewport?
首先,看一下设备上浏览器的默认viewport的宽度:
如果把移动设备上浏览器的可视区域设为viewport的话,某些网站就会因为viewport太窄而显示错乱,所以这些浏览器就决定默认情况下把viewport设为一个较宽的值,比如980px,这样的话即使是那些为桌面设计的网站也能在移动浏览器上正常显示了。ppk把这个浏览器默认的viewport叫做 layout viewport。这个layout viewport的宽度可以通过 document.documentElement.clientWidth
来获取。
然而,layout viewport 的宽度是大于浏览器可视区域的宽度的,所以我们还需要一个viewport来代表浏览器可视区域的大小,ppk把这个viewport叫做 visual viewport。visual viewport的宽度可以通过 window.innerWidth
来获取,但在Android 2, Oprea mini 和 UC8中无法正确获取。
当然由上图可见,每个浏览器默认的viewpoint是不一样的,所谓的完美适配指的是,首先不需要用户缩放和横向滚动条就能正常的查看网站的所有内容;第二,显示的文字的大小是合适,比如一段14px大小的文字,理想的情况是这段14px的文字无论是在何种密度屏幕,何种分辨率下,显示出来的大小都是差不多的。当然,不只是文字,其他元素像图片什么的也是这个道理。ppk把这个viewport叫做 ideal viewport,也就是第三个viewport——移动设备的理想viewport。
ideal viewport并没有一个固定的尺寸,不同的设备拥有有不同的ideal viewport。6以前的所有iphone的ideal viewport宽度都是320px,后来出现了375px, 414px, 安卓设备也是比较复杂了,有320px的,有360px的,600px, 800px的等等,关于不同的设备ideal viewport的宽度都为多少,可以到http://viewportsizes.com去查看一下,里面收集了众多设备的理想宽度。
mata标签与viewport的关系
大家应该都有印象,head标签中的
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
移动设备默认的是 layout viewport , 但是我们需要的是 ideal viewport, 那么通过meta标签的作用就是:让当前viewport的宽度等于设备的宽度,同时不允许用户手动缩放。
meta viewport 标签首先是由苹果在其safari浏览器中引入的,目的就是解决移动设备的viewport问题。后来安卓以及各大浏览器厂商也都纷纷效仿,引入对meta viewport的支持,事实也证明这个东西还是非常有用的。
在苹果的规范中,meta viewport 有6个属性(暂且把content中的那些东西称为一个个属性和值),如下:
- width 设置layout viewport 的宽度,为一个正整数,或字符串"width-device"
- initial-scale 设置页面的初始缩放值,为一个数字,可以带小数
- minimum-scale 允许用户的最小缩放值,为一个数字,可以带小数
- maximum-scale 允许用户的最大缩放值,为一个数字,可以带小数
- height 设置layout viewport 的高度,这个属性对我们并不重要,很少使用
- user-scalable 是否允许用户进行缩放,值为"no"或"yes", no 代表不允许,yes代表允许
在安卓中还支持 target-densitydpi 这个私有属性,当然17年就已经快要废弃了,有兴趣的同学自己看一下啦。
meta 如何控制 viewport ?
要得到ideal viewport就必须把默认的layout viewport的宽度设为移动设备的屏幕宽度。因为meta viewport中的width能控制layout viewport的宽度,所以我们只需要把width设为width-device这个特殊的值就行了。
<meta name="viewport" content="width=device-width">
但是,你肯定不知道
<meta name="viewport" content="initial-scale=1">
这句代码也能达到和前一句代码一样的效果,也可以把当前的的viewport变为 ideal viewport。
因为这里的缩放值是1,也就是没缩放,但却达到了 ideal viewport 的效果,所以,那答案就只有一个了,缩放是相对于 ideal viewport来进行缩放的,当对ideal viewport进行100%的缩放,也就是缩放值为1的时候,就得到了 ideal viewport 。事实证明,的确是这样的。
但如果width 和 initial-scale=1同时出现,并且还出现了冲突呢?比如:
<meta name="viewport" content="width=400, initial-scale=1">
width=400表示把当前viewport的宽度设为400px,initial-scale=1则表示把当前viewport的宽度设为ideal viewport的宽度,那么浏览器到底该服从哪个命令呢?是书写顺序在后面的那个吗?不是。当遇到这种情况时,浏览器会取它们两个中较大的那个值。例如,当width=400,ideal viewport的宽度为320时,取的是400;当width=400, ideal viewport的宽度为480时,取的是ideal viewport的宽度。(ps:在uc9浏览器中,当initial-scale=1时,无论width属性的值为多少,此时viewport的宽度永远都是ideal viewport的宽度)
最后,总结一下,要把当前的viewport宽度设为ideal viewport的宽度,既可以设置 width=device-width,也可以设置 initial-scale=1,但这两者各有一个小缺陷,之前就是iphone、ipad以及IE 会横竖屏不分,通通以竖屏的ideal viewport宽度为准。所以,最完美的写法应该是,两者都写上去,这样就 initial-scale=1 解决了 iphone、ipad的毛病,width=device-width则解决了IE的毛病:
<meta name="viewport" content="width=device-width, initial-scale=1">
博主小号-欢迎关注话说小主开了一个wx号:[
民间程序员
],分享H5相关知识点,H5踩坑记,H5实战案例分享等,欢迎大家关注~