在说具体内容之前,我们必须了解几个概念,就是:Retina屏、物理像素、设备独立像素、设备像素比
在CSS中我们一般使用px作为单位,需要注意的是,CSS样式里面的px和物理像素并不是相等的。CSS中的像素只是一个抽象的单位,在不同的设备或不同的环境中,CSS中的1px所代表的物理像素是不同的。在PC端,CSS的1px一般对应着电脑屏幕的1个物理像素,但在移动端,CSS的1px等于几个物理像素是和屏幕像素密度有关的。
1.Retina屏
所谓“Retina”是一种显示标准,是把更多的像素点压缩至一块屏幕里,从而达到更高的分辨率并提高屏幕显示的细腻程度。由摩托罗拉公司研发。最初该技术是用于Moto Aura上。这种分辨率在正常观看距离下足以使人肉眼无法分辨其中的单独像素。也被称为视网膜显示屏。
Retina屏一般在苹果公司的产品上用的比较多,诸如MacBook、iPad、iPhone等
以MacBook Pro with Retina Display为例,工作时显卡渲染出2880x1800个像素,其中每四个像素一组,输出原来屏幕的一个像素显示的大小区域内的图像。这样一来,用户所看到的图标与文字的大小与原来的1440x900分辨率显示屏相同,但精细度是原来的4倍,但对于特殊元素,如视频与图像,则以一个图片像素对应一个屏幕像素的方式显示。故不会产生Windows中分辨率提升使屏幕文字与图像变小,造成阅读困难的问题。这样在设计软件时只需将所有的UI元素的精细度都提高到原来的4倍就可以既保持了观看舒适度,又提高了显示效果。关于iOS设备,也由四个像素代替原来一个像素,通过下图对比就可以较明显地观察到这种关系
2.物理像素(physical pixel)
物理像素又被称为设备像素、设备物理像素,它是显示器(电脑、手机屏幕)最小的物理显示单位,每个物理像素由颜色值和亮度值组成。所谓的一倍屏、二倍屏(Retina)、三倍屏,指的是设备以多少物理像素来显示一个CSS像素,也就是说,多倍屏以更多更精细的物理像素点来显示一个CSS像素点,在普通屏幕下1个CSS像素对应1个物理像素,而在二倍Retina屏幕下,1个CSS像素对应的却是4个物理像素(参照上面Retina屏的原理下文田字示意图理解)。
3.设备独立像素(device-independent pixel)
设备独立像素是我们写CSS时所用的像素,它是一个抽像的单位,主要使用在浏览器上,用来精确度量Web页面上的内容。
4.设备像素比(device pixel ratio)
设备像素比简称为dpr,物理像素与设备独立像素的比例。
当这个比率为1:1时,使用1个设备像素显示1个css像素。当这个比率为2:1=2时,使用4(2*2)个设备像素显示1个css像素。当这个比率为3:1=3,使用9(3*3)个设备像素显示1个css像素。
这里要注意,dpr=2,并不是物理像素是设备独立像素的2倍,而是用4个物理像素去表示1个设备逻辑像素
应该说1个设备独立像素是1个物理像素的4倍!!!!!,因为你4个网物理像素才代表我1个设备独立像素
dpr只代表一个数字比例,不是倍数关系。
CSS的1px等于几个物理像素,除了和屏幕像素密度dpr有关,还和用户缩放有关系。例如,当用户把页面放大一倍,那么CSS中1px所代表的物理像素也会增加一倍;反之把页面缩小一倍,CSS中1px所代表的物理像素也会减少一倍。关于这点,在文章后面的1px细线问题部分还会讲到。
viewport
viewport就是设备上用来显示网页的那一块区域,但viewport又不局限于浏览器可视区域的大小,它可能比浏览器的可视区域要大,也可能比浏览器的可视区域要小。
在默认情况下,一般来讲,移动设备上的viewport都是要大于浏览器可视区域的,这是因为考虑到移动设备的分辨率相对于桌面电脑来说都比较小,所以为了能在移动设备上正常显示那些传统的为桌面浏览器设计的网站,移动设备上的浏览器都会把自己默认的viewport设为980px或1024px(也可能是其它值,这个是由设备自己决定的),但带来的后果就是浏览器会出现横向滚动条,因为浏览器可视区域的宽度是比这个默认的viewport的宽度要小的。
这里要认清三种视口
- visual viewport 可见视口,指屏幕宽度
- layout viewport 布局视口,指DOM宽度
- ideal viewport 理想适口,使布局视口就是可见视口即为理想视口
获取屏幕宽度(visual viewport)的尺寸:
window. innerWidth/Height
获取DOM宽度(layout viewport)的尺寸:
document. documentElement. clientWidth/Height
设置理想视口ideal viewport:
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
该meta标签的作用是让layout viewport的宽度等于visual viewport的宽度,同时不允许用户手动缩放,从而达到理想视口。
-
meta[name="viewport"]里各参数的含义为:
-
-
width: 设置layout viewport 的宽度,为一个正整数,或字符串”width-device”。
-
-
initial-scale: 设置页面的初始缩放值,为一个数字,可以带小数。
-
-
minimum-scale: 允许用户的最小缩放值,为一个数字,可以带小数。
-
-
maximum-scale: 允许用户的最大缩放值,为一个数字,可以带小数。
-
-
height: 设置layout viewport 的高度,这个属性对我们并不重要,很少使用。
-
-
user-scalable: 是否允许用户进行缩放,值为“no”或“yes”。
1 rem适配
哇卡卡卡,终于说到移动端屏幕适配方案了,可能大家看的想骂娘了,不过别急啊,上面的东西弄不清楚,下面是适配也听不懂啊
rem是相对于根元素的字体大小的单位,也就是html的font-size大小,浏览器默认的字体大小是16px,所以默认的1rem=16px,我们可以根据设备宽度动态设置根元素的font-size,使得以rem为单位的元素在不同终端上以相对一致的视觉效果呈现。
事实上 rem是把屏幕等分成 指定的份数,以20份为例,每份为 1rem , 1rem 对应的大小就是 rem基准值 ,rem做的就是把 rem基准值 给<html>
的 font-size ,所以如果设备的 物理像素 宽为 640px ,分成20份,那么 1rem=640px/20=32px , <html>
的 font-size为32px 。
-
//这段代码放在head标签里面
-
(function () {
-
var html = document.documentElement;
-
-
function onWindowResize() {
-
html.style.fontSize = html.getBoundingClientRect().width / 20 + 'px';
-
}
-
-
window.addEventListener('resize', onWindowResize);
-
onWindowResize();
-
})();
-
当然,你也可以分成30份,40份,60份等等,这个看自己的喜好了
在我们实际切图的时候,对于视觉稿上的元素尺寸换算,只需要元素的 原始的px值(即你量的大小) 除以 rem基准值 即可。例如设计稿的大小为640px, rem基准值 = 640px/20 = 32px ,有个元素的大小你量出来是 140px286px* ,那么换算过来就是:
-
140px = 140/32 = 4.375rem
-
286px = 286/32 = 8.9375rem
这样我们就可以用rem来代替像素px了, 而且在所有的移动端都是自适应的
这个方法目前是比较好的适配方法,只是rem在计算时很麻烦,有很多小数,这个时候大家可以试一下用less.js解决rem的小数问题
2 rem+vw适配
什么是vw和vh?
- vw : 1vw 等于视口宽度的1%
- vh : 1vh 等于视口高度的1%
- vmin : 选取 vw 和 vh 中最小的那个
- vmax : 选取 vw 和 vh 中最大的那个
用视口单位度量,视口宽度为100vw,高度为100vh(左侧为竖屏情况,右侧为横屏情况)
例如,在桌面端浏览器视口尺寸为650px,那么 1vw = 650 * 1% = 6.5px(这是理论推算的出,如果浏览器不支持0.5px,那么实际渲染结果可能是7px)
注意:这里的1%是指占视口的1%,而不是我们定义的div的1%
如何利用rem+vw进行屏幕适配呢?我们以设计稿为750px为基准
第一步:设置meta标签
<meta name="viewport" content="width=device-width, initial-scale=2.0, maximum-scale=2.0, minimum-scale=2.0, user-scalable=no">
因为iPhone6以及大多数的dpr为2,为了第二步的方便进行换算
第二步:设置html的font-size大小
html{font-size:13.33333333vw}
为什么font-size=13.33333333vw?
下面分析下原理吧, 上面我们说了vw表示1%的屏幕宽度,而我们的设计稿通常是750px的,屏幕一共是100vw,对应750px,那么1px就是0.1333333vw,。
同时我们知道rem,rem是相对html元素的字体大小,为了方便计算,我们取html的font-size=100px,通过上面的计算结果1px是0.13333333vw,那么100px就是13.333333vw了
所以,我们让1rem=100px=13.333333vw
那么在项目上就很好地可以进行使用了
当我们通过ps测量一个div的大小为 width:200px,height:137px时,我们就可以这样写,ps量出来的像素直接除以100,计算小数很方便
-
div {
-
width: 2rem;
-
height:1.37rem;
-
-
}
是不是相对于前面的rem适配来说,不用去计算小数了呢?
但是注意,这是针对于dpr=2的适配,至于其他dpr适配,要根据设计师的设计稿规定
1)如果你的设计图是640px或者750px,那么dpr的取值就是2,meta如下设置
<meta name="viewport" content="width=device-width, initial-scale=2.0, maximum-scale=2.0, minimum-scale=2.0, user-scalable=no">
3)如果你的设计图是1080px,那么css像素就是1080px,那么dpr的取值就是3,这个时候,meta要如下设置
<meta name="viewport" content="width=device-width, initial-scale=3.0, maximum-scale=3.0, minimum-scale=3.0, user-scalable=no">
然后rem的计算方法和dpr=2时一样。
rem+vw适配解决了小数问题,但是兼容性不太好,所以看大家怎么选择了