一直以来,web移动端都有这么几个问题困扰着我:

单位太多,除了px、rem,其他单位到底啥意思?

设计师经常会问前端,我到底按照什么尺寸出设计稿?

高清图怎么做出来的?

边框1px,为什么在不同手机中粗细完全不同?

妈蛋,为何移动端总要在meta中width=device-width, initial-scale=1…写这么一句

什么是viewport?

我相信我的问题也困扰着你,且听我娓娓道来…

一、单位

先来罗列下学习移动页面重构的过程中可能看到过迷糊过放弃过的一些单位:

px、pt、pc、sp、em、rem、dp、dip、ppi、dpi、ldpi、mdpi、hdpi、xhdpi、xxhdpi……

接下来分类给大家介绍下:

① 什么是绝对长度单位?什么是相对长度单位?

② 什么是屏幕尺寸、屏幕分辨率、屏幕像素密度?

③ 什么是ppi、dpi、dp、dip、sp、px?他们之间的关系是什么?

④ 什么是mdpi、hdpi、xdpi、xxdpi?

⑤ dpi和转换参数的关系?

⑥dpr是什么?

(1)什么是绝对长度单位?什么是相对长度单位?

绝对长度单位:in(inch英寸)、cm(厘米)、mm(毫米)、pt(磅)、pc(pica)。网页中应用比较少。

相对长度单位:是网页设计中使用最多的长度单位,包括px、em、rem等。

(2)什么是屏幕尺寸、屏幕分辨率、屏幕像素密度?

屏幕尺寸:指屏幕的对角线的长度,单位是英寸,1英寸=2.54厘米。常见的屏幕尺寸有2.4、2.8、3.5、3.7、4.2、5.0、5.5、6.0等。

iOS 获取手机的屏幕密度ppi_iOS 获取手机的屏幕密度ppi

屏幕分辨率:指在横纵向上的像素点数,单位是px,1px=1个像素点。一般以纵向像素*横向像素来表示一个手机的分辨率,如1960*1080。(忽略图片中的蓝色点,主要看红色点)

iOS 获取手机的屏幕密度ppi_iOS 获取手机的屏幕密度ppi_02

屏幕像素密度:屏幕上每英寸可以显示的像素点的数量,单位是dpi或ppi。在单一变化条件下,屏幕尺寸越小、分辨率越高,像素密度越大,反之越小。

最明显的就是iPhone 3GS和iPhone 4的区别。屏幕尺寸一样,屏幕分辨率相差一倍,屏幕像素密度也相差一倍。

iOS 获取手机的屏幕密度ppi_移动_03

计算像素密度的公式:

iOS 获取手机的屏幕密度ppi_viewport_04

勾股定理算出对角线的分辨率:√(1920^2+1080^2)≈2203px

对角线分辨率除以屏幕尺寸:2203/5≈440dpi。

(3)什么是ppi、dpi、dp、dip、sp、px?

ppi和dpi:屏幕上每英寸可以显示的像素点的数量,即屏幕像素密度。ppi和dpi是同一个概念,Android比较喜欢使用dpi,IOS比较喜欢使用ppi。

dp、dip:都是密度独立像素,可以想象成是一个物理尺寸,使同样的设置在不同手机上显示的效果看起来是一样的。

(如图所示蓝色点,虽然不同分辨率的手机,但是其物理大小一样)

iOS 获取手机的屏幕密度ppi_viewport_05

px:将显示器分成非常细小的方格,每个方格就是一个像素(上图所示红色点)。从上图可以看出不同屏幕下的每个px大小是不一样的。

(4)什么是mdpi、hdpi、xdpi、xxdpi?

Google官方指定按照下列标准区分不同设备的dpi:

iOS 获取手机的屏幕密度ppi_移动_06

苹果的区分则更为简单:非高清屏、高清屏、超高清屏。(dpi值越大越清晰)

iOS 获取手机的屏幕密度ppi_iOS 获取手机的屏幕密度ppi_07

(5) dpi和转换参数的关系?

dpi我们都知道,是指像素密度;转换参数是指,dp与px之间的转换系数。

如下图,dp指蓝色块,px指红色块,很明显密度更大的右图中每个dp含有的px个数更多。转换参数 = px / dp (公式自己总结,可以忽略),可以得出结论:dpi密度越大,转换参数越大。

iOS 获取手机的屏幕密度ppi_单位_08

根据上面得出结论,dpi越大的,转换参数就会越大,例如下图中160dpi,对应的转换参数为“1x”;而240dpi,为“1.5x”。

具体转换参数1x,1.5x等如何算出来的,你可以不用理会,只要知道xxxdpi对应下图哪种系列的转换参数即可。

iOS 获取手机的屏幕密度ppi_单位_09

转换参数的作用,举个栗子:

在Android中,规定以160dpi的转换参数是1x,那么1dp=1px。如果密度是320dpi参数属于2x,则1dp=2px,以此类推。

(6)dpr是什么?

要了解dpr,先要知道物理像素和设备独立像素。

物理像素:

其实就是指设备最小像素点,其实就是下图中的红点,原谅我总用一张图。

iOS 获取手机的屏幕密度ppi_移动_10

设备独立像素:

就是下图蓝点,和dp有点像,但是概念不要混淆。它也是一样的,不同设备物理大小总是一样。

iOS 获取手机的屏幕密度ppi_移动_11

在不同的屏幕上(普通屏幕 vs retina屏幕),设备独立像素所呈现的大小(物理尺寸)是一致的,不同的是1个设

备独立像素(蓝点)所对应的物理像素(红点)个数是不一致的。

在普通屏幕下,1个设备独立像素 对应 1个物理像素(1:1)。

在retina 屏幕下,1个设备独立像素对应 x个物理像素(1:x)。

公式:

dpr = 物理像素 / 设备独立像素 ; 虽然我们有公式,但是并不需要用,因为dpr可以直接由js的内置属性可

以获得。

dpr = window.devicePixelRatio;

二、高清图

(1)位图像素:

一个位图像素是栅格图像(如:png, jpg, gif等)最小的数据单元。

(2)谈到这里,就得说一下,高清图原理?

理论上,1个位图像素对应于1个物理像素(红色点),图片才能得到完美清晰的展示。

在普通屏幕下是没有问题的,但是在retina屏幕下就会出现位图像素点不够,从而导致图片模糊的情况。

用一张图来表示:

iOS 获取手机的屏幕密度ppi_iOS 获取手机的屏幕密度ppi_12

如上图:对于dpr=2的retina屏幕而言,1个位图像素对应于4个物理像素,由于单个位图像素不可以再进一步分割,所以只能就近取色,从而导致图片模糊(注意上述的几个颜色值)。

所以,对于图片高清问题,比较好的方案就是两倍图片(@2x)。

如:200×300(css pixel)img标签,就需要提供400×600的图片。

如此一来,位图像素点个数就是原来的4倍,在retina屏幕下,位图像素点个数就可以跟物理像素点个数形成 1 : 1的比例,图片自然就清晰了(这也解释了为啥视觉稿的画布大小要×2?)。

(3)这里就还有另一个问题,如果普通屏幕下,也用了两倍 图片,会怎样呢?

在普通屏幕下,200×300(css pixel)img标签,所对应的物理像素个数就是200×300个,而两倍图片的位图像素个数则是200×300*4,所以就出现一个物理像素点对应4个位图像素点,所以它的取色也只能通过一定的算法downsampling,肉眼看上去虽然图片不会模糊,但是会觉得图片缺少一些锐利度,或者是有点色差(但还是可以接受的)。

iOS 获取手机的屏幕密度ppi_viewport_13

(4)得出结论:

一般来说dpr = 2为多,dpr = 1 为普通屏幕,dpr = 3占少数。所以我们至少做2套图片,一套是兼容dpr = 1的小图;一套是兼容dpr = 2的大图;dpr = 3的可以兼容到dpr = 2的图片中,虽然有点失色,但还是可以接受的。

这是不是意味着设计师必须做两套图片呢?其实并不需要,设计师只需做一套x2的大图,例如320 * 100的img标签,做成640*200的图片即可。

小图则可以让后台服务器根据x2大图,再次生成一套小图即可。

(5)CSS中高清适配解决方案:

.imgs{/* 普通显示屏(设备像素比例小于等于1)使用1倍的图 */ 
    background-image: url(img_1x.png);
}
@media only screen and (-webkit-min-device-pixel-ratio:2){
.imgs{/* 高清显示屏(设备像素比例大于等于2)使用2倍图  */
    background-image: url(img_2x.png);
  }
}

三、1px边框

(1)什么是1px边框?

iOS 获取手机的屏幕密度ppi_web_14

上图中,对于一条 1px 宽的直线,它们在屏幕上的物理尺寸(灰色区域)的确是相同的,不同的其实是屏幕上最小的物理显示单元,即物理像素,所以对于一条直线,iphone5它能显示的最小宽度其实是图中的红线圈出来的灰色区域,用css来表示,理论上说是 0.5px 。(css像素在不同设备上的物理大小是一样的)

所以,设计师想要的retina下 border: 1px; ,其实就是1物理像素宽,对于css而言,可以认为是 border: 0.5px; ,这是retina下(dpr=2)下能显示的最小单位。

然而,无奈并不是所有手机浏览器都能识别 border: 0.5px; ,ios7以下,android等其他系统里,0.5px会被当成为0px处理,那么如何实现这 0.5px 呢?

(2)解决方案:

利用transform:scale(x,y),设置线条为1px,然后通过transform:scale(x,y)来缩放线条为原来的一半,可显示0.5px的线条。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta content="width=device-width,initial-scale=1,maximum-scale=1.0,user-scalable=no" name="viewport">
<meta content="yes" name="apple-mobile-web-app-capable">
<meta content="black" name="apple-mobile-web-app-status-bar-style">
<meta content="telephone=no" name="format-detection">
<meta content="email=no" name="format-detection">
<title>点5测试 - scale</title>
<style type="text/css">
.line {
    height: 50px;
    line-height: 50px;
    background-color: #CCC;
    border-bottom:1px solid red
} 

.scale {
    position: relative;
    height: 50px;
    line-height: 50px;
    background-color: #CCC
}
.scale:after {
    position: absolute;
    content: '';
    width: 100%;
    left: 0;
    bottom: 0;
    height: 1px;
    background-color: red;
    -webkit-transform: scale(1,.5);
    transform: scale(1,.5);
    -webkit-transform-origin: center bottom;
    transform-origin: center bottom
}
</style>
</head>

<body>
<div class="line">1px</div>
<br/><br/>    
<div class="scale">0.5px</div>
</body>

</html>

看效果:

iOS 获取手机的屏幕密度ppi_web_15

四、深入理解viewport

(1)viewport默认宽度

手机浏览器是把页面放在一个虚拟的“窗口”(viewport)中,不做任何设置的移动设备,默认大小一般是980px。

iOS 获取手机的屏幕密度ppi_viewport_16

例如iPhone4S如果不设置viewport,他就会默认是980px,就像把屏幕分成980份(不是屏幕分辨率的640px哦!)。如果设置一个元素为100px*100px,看起来就是屏幕的100/980,可能如下图所示:

iOS 获取手机的屏幕密度ppi_web_17

(2)自定义viewport宽度

所以为了让100px的元素不这么小,必须将默认980去掉,改成更小的值,如何改呢?

iOS 获取手机的屏幕密度ppi_单位_18

每个设置对应的是:

iOS 获取手机的屏幕密度ppi_web_19

例如iPhone4S如果设置viewport width=device-width,他就会是320px,就像把屏幕分成320份。如果设置一个元素为100px*100px,看起来就是屏幕的100/320,可能如下图所示:

iOS 获取手机的屏幕密度ppi_iOS 获取手机的屏幕密度ppi_20

那么device-width就是屏幕分辨率的宽度?

其实不是的,例如iPhone6的屏幕分辨率是1334*750px,ppi是326,所以系数是2x。那device-width就等于750/2=375px。

参考链接:

  1. 高清屏retina屏适配的解决方案
  2. 深度讲解VIEWPORT
  3. 高清图片适配解决方案
  4. 高清显示屏原理及设计方案
  5. 移动web点5像素的秘密
  6. 移动前端开发之viewport的深入理解
  7. 移动端屏幕分辨率查看大全
  8. Html开发之Viewport的使用
  9. dpr与dp和px转换公式
  10. 移动web开发之像素和DPR
  11. 移动端高清、多屏适配方案——rem
  12. 移动端高清、多屏适配方案
  13. CSS布局基础之一设备像素,设备独立像素
  14. 设备像素比devicePixelRatio
  15. 设备像素,CSS像素和屏幕分辨率