移动端像素的概念
移动端有两种像素的概念,一种是设备物理像素,另一种是设备逻辑像素,设备逻辑像素是与设备物理像素无关的。
比如,iPhone的屏幕分辨率:
- iPhone5 :逻辑像素分辨率 320 * 568,物理像素分辨率 640 * 1136(设备像素比为2)
- iPhone6:逻辑像素分辨率 375 * 667,物理像素分辨率 750 * 1334(设备像素比为2)
- iPhone6 Plus :逻辑像素分辨率 414 * 736,物理像素分辨率 1242 * 2208(设备像素比为3)
目前手机系统一般分为android和iphone,这两个系统为了适配不同屏幕尺寸,定义了一些标准和单位,原理都差不多,在开发中用逻辑单位去代替物理单位,再使用设备像素比进行换算。
Iphone手机相关的单位和标准
- PPI:每英寸(物理尺寸)长度上像素点的个数
- pt:point,ios开发中的布局长度单位(类似css中的px,都是逻辑抽象单位)
- DPI:每英寸(物理尺寸)长度上点(即上面的pt)的个数,可以理解为每英寸上的抽象点的个数
Andorid手机相关的单位和标准
- DPI:每英寸(物理尺寸)长度上像素点的个数(和IOS中的PPI是一致的)
- dp:android开发中的布局长度单位,和ios中的pt概念一样(类似css中的px,都是逻辑抽象单位)
- sp:和dp一样,只不过是用来设定字体大小的,sp设定字体大小可以随用户的缩放而改变大小
了解了android开发和ios开发中相关的手机适配方案后再来看下移动端浏览器中的手机适配方案,因为浏览器手机适配是不分ios和android的,所以其比上面两种适配方案更加复杂。在浏览器中通过window.outerWidth可以获取到设备的逻辑分辨率宽。
移动端浏览器视口(viewport)的概念
通过上面的手机尺寸,大家应该都知道,在pc端的网页宽度一般都是要比手机的逻辑分辨率宽度要大很多的,所以为了让pc端的网页能够完整的显示移动端浏览器上,必须再通过通过一个标准去缩放网页,而不仅仅是靠手机本身的设备像素比去,因为手机的设备像素比是固定的。于是以苹果公司为主导的手机生产厂商都给浏览器加了一个默认的视口(viewport)来解决网页缩放的问题,这个默认的视口宽度为980px。
viewport分为visual viewport(度量视口)和layout viewport(布局视口)。
对于移动端来说,visual viewport就是你通过浏览器所看到的那部分大小,可通过window.innerWidth得到未缩放前的visual viewport的宽度,它的度量单位是px(css中的逻辑像素单位),可以通过放大缩小改变visual viewport的大小。
和visual viewport相对应的另外一个viewport叫layout viewport,可通过document.body.clientWdith得到其宽度。它就相当于一个大的box,所有的内容都要在这个box里面显示,layout viewport不会随放大缩小而改变大小,你通过visual viewport所看到的内容就是layout viewport上的部分内容。安卓和iphone手机浏览器默认layout viewport的宽度是980px。两个视口的换算公式为layout viewport*缩放比=visual viewport。
需要注意的是:当元素的宽度大于layou viewport的宽度或者visual viewport的宽度大于设备的逻辑分辨率宽的时候,将出现横向滚动条。
为了加深理解,请看以下例子:
<!DOCTYPE>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
body{
margin:0;
padding-top: 0;
}
#d1{
width: 1200px;
height: 100px;
background: red;
}
</style>
</head>
<body>
<div id='d1'></div>
</body>
<script type="text/javascript">
</script>
</html>
iPhone5模拟下:
iPhone6模拟结果:
了解了view port以后,大家应该不难理解,css中的px其实是一个逻辑单位,它和设备物理分辨率里的px像素是完全不同的,可以把它理解为一个百分百单位,如果把布局视口宽度定义为320px,让网页缩放至刚好占满整个设备屏幕的宽度,则1px的宽度在物理上等于1/320*设备的物理宽度,所以说css中的1px代表的物理宽度是可控可调节的,是一个相对单位。
对于meta标签,如果我们只定义了initial-scale,则width默认为设备逻辑分辨率宽度/initial-scale,如果只定义了width,则initial-scale默认为设备逻辑分辨率宽度/width。所以在屏幕逻辑分辨率宽为320px的设备下,下面三个meta标签的效果是一样的:
<meta name="viewport" content="width=640"/>
<meta name="viewport" content="initial-scale=0.5"/>
<meta name="viewport" content="width=640,initial-scale=0.5"/>
通常为了防止用户手动缩放屏幕大小,会给meta标签加个user-scalable=no:
<meta name="viewport" content="width=640,user-scalable=no"/>
target-densitydpi
一个屏幕像素密度是由屏幕分辨率决定的,通常定义为每英寸点的数量(dpi)。Android支持三种屏幕像素密度:低像素密度,中像素密度,高像素密度。一个低像素密度的屏幕每英寸上的像素点更少,而一个高像素密度的屏幕每英寸上的像素点更多。Android Browser和WebView默认屏幕为中像素密度。
下面是 target-densitydpi 属性的 取值范围:
- device-dpi –使用设备原本的 dpi 作为目标 dp。 不会发生默认缩放。
- high-dpi – 使用hdpi 作为目标 dpi。 中等像素密度和低像素密度设备相应缩小。
- medium-dpi – 使用mdpi作为目标 dpi。 高像素密度设备相应放大, 像素密度设备相应缩小。 这是默认的target density.
- low-dpi -使用mdpi作为目标 dpi。中等像素密度和高像素密度设备相应放大。
- – 指定一个具体的dpi 值作为target dpi. 这个值的范围必须在70–400之间。
当 target-densitydpi=device-dpi 时, css中的1px会等于物理像素中的1px。打个比方,默认情况下一张320* 480的图片在iPhone4里是占满的,因为iPhone4的逻辑分辨率为320* 480。但是当target-densitydpi=device-dpi时,320* 480的图片在iPhone4里只占屏幕的一半,因为iPhone4的物理分辨率为640* 960。
因为这个属性只有安卓支持(andorid4.0以下的手机不支持viewport的width属性,可以用target-densitydpi代替),并且安卓已经决定要废弃 target-densitydpi 这个属性了,尽量避免使用这个属性。
如果在支持width属性的安卓设备上使用了target-densitydpi=device-dpi,则相当于同时设置了width=设备物理分辨率,initial-scale=1/设备像素比,如果设备物理分辨率为1080,设备像素比为3,则下面两个viewport效果是一样的(因为不能整除的原因,有细微差别):
<meta name="viewport" content="target-densitydpi=device-dpi">
<meta name="viewport" content="width=1080,initial-scale=0.33">
如果同时设置了width和target-densitydpi,则如果width的取值为较大的那个值,如果还定义了initial-scale,则将覆盖默认的initial-scale=1/设备像素比。
还是以1080宽的设备物理分辨率为准,设备像素比为3:
<meta name="viewport" content="target-densitydpi=device-dpi,width=720,initial-scale=1">
最终结果为:width=1080,initial-scale=1
<meta name="viewport" content="target-densitydpi=device-dpi,width=1200,initial-scale=0.333">
最终结果为:width=1200,initial-scale=0.333
以上结果全部在魅族MX5手机上测试