一 像素知识
1.1 设备像素(device pixel)
它是物理概念,指的是设备中使用的物理像素(Physic pixel)。这个单位用px表示,它是一个[相对绝对单位]————
即在同样一个设备上,每1个设备像素所代表的物理长度(如英寸)是固定不变的(即设备像素的绝对性);
但在不同的设备之间,每1个设备像素所代表的物理长度(如英寸)是可以变化的(即设备像素的相对性);
我们所说的设备分辨率的单位就是设备像素。
有了设备像素概念,我们就可以解释下表中:不同英寸大小的移动设备上,分辨率却相同的原因了————因为设备像素的相对性
手机类型 | 华为荣耀8 | IPhone6S Plus |
---|---|---|
屏幕尺寸 | 5.2英寸 | 5.5 英寸 |
分辨率 | 1920x1080 | 1920 x 1080 |
PPI | 423 | 401 |
注:表格中的数据来源
华为荣耀8:http://www.vmall.com/product/938665621.html
IPhone6S Plus:https://www.apple.com/cn/iphone-6s/specs/
1.1.1 设备分辨率
设备分辨率的单位就是设备像素(px)。
提到设备分辨率,顺便引用如下地址的博客说明一下:
http://www.chinaz.com/manage/2015/0902/441624.shtml
在同一个手机或电脑设备上,它的设备像素是固定的,这是厂商在出厂时就设置好了的————即一个设备的分辨率是固定不变的。
所以可以调整电脑屏幕的分辨率(手机就没这个功能!)?那只是你的眼睛在欺骗你,具体原因请见:
http://www.chinaz.com/manage/2015/0902/441624.shtml <电脑屏幕可以调分辨率,难道是通过调整它的像素大小实现的?>一节
1.2 CSS像素(css pixel)
设备像素和CSS像素一般使用px作为单位,并且在桌面浏览器的100%缩放情况下,css的1个像素往往都是对应着电脑屏幕的1个物理像素,这可能会造成我们的一个错觉,那就是css中的像素就是设备的物理像素。
但实际情况却并非如此,css像素只是一个抽象的单位,在不同的设备或不同的环境中,css中的1px所代表的设备物理像素的长度是不同的。
在为桌面浏览器设计的网页中,我们无需对这个津津计较,但在移动设备上,必须弄明白这点。
上述论述得到如下结论:
css中的1px并不是总代表设备像素上的1px,尤其是在移动设备上。
CSS像素是Web编程的概念,指的是CSS样式代码中使用的逻辑像素。它是一个[纯相对单位]————
在同样一个设备上,每1个CSS像素所代表的物理像素是可以变化的(即CSS像素的第一方面的相对性);
在不同的设备之间,每1个CSS像素所代表的物理像素是可以变化的(即CSS像素的第二方面的相对性);
从上述定义可以看出:
CSS像素是一个相对单位,相对的是设备像素(device pixel)。
(原文地址:http://www.jianshu.com/p/af6dad66e49a)
1.2.1 缩放
引用PPK大神的论述来说明一下缩放的原理:
Zooming as implemented in modern browsers consists of nothing more than “stretching up” pixels. That is, the width of the element is not changed from 128 to 256 pixels; instead the actual pixels are doubled in size. Formally, the element still has a width of 128 CSS pixels, even though it happens to take the space of 256 device pixels. (原文网址:http://www.quirksmode.org/mobile/viewports.html)
译文:
现代浏览器中实现缩放的方式都是「拉伸」像素(即每CSS像素单位代表的长度发生变化,而像素总数字不变)。(如果将一个元素为128px的元素放大一倍, 译者注)元素的宽度并没有从128px变到256px,事实上只是“实际像素”变为2倍大小(即256px),而形式上这个元素的宽度还是128px,尽管它已经占据了256个设备像素的空间。
所以,我们可以得到如下结论:
缩放会引起CSS像素的变化——即引起每1个CSS像素所代表的物理像素变化。例如,当用户把页面放大一倍,那么css中1px所代表的物理像素也会增加一倍;反之把页面缩小一倍,css中1px所代表的物理像素也会减少一倍。
所以,有上述描述,我们可以得到如下结论:
页面缩放比例 = 物理像素/CSS像素
1.3 DPI&PPI
引用 http://weizhifeng.net/you-should-know-about-dpi.html 中关于DPI和PPI的定义如下:
DPI(dots per inch)为打印机每英寸可以喷的墨汁点数,用于印刷行业中度量空间点的密度
PPI(pixels per inch)为屏幕每英寸的像素数量(即在一个对角线长度为1英寸的正方形内所拥有的像素数),用于度量计算机显示屏上像素的密度
目前PPI(主要是iOS)和DPI(比如在Android中)都会用在计算机显示设备的参数描述中,并且二者的意思是一样的,都是代表像屏幕素密度
屏幕像素密度,屏幕分辨率,屏幕尺寸三者的关系如下:
注:上图公式中,如分辨率为1920px*1080px,则1920px就是公式里的纵向,1080px就是公式里的横向了
1.4 DPR
全称设备像素比(Device Pixel Ratio)。先给出其官方定义:
在移动端浏览器中以及某些桌面浏览器中,window对象有一个devicePixelRatio属性,它的官方的定义为:设备物理像素和设备独立像素的比例,也就是 devicePixelRatio = 物理像素 / 独立像素。
由上述公式计算出ppi是为了得到密度分界,获得默认缩放比例,即设备像素比–dpr
安卓的设备像素比如下:
由上图可知,ppi在120-160之间的手机被归为低密度手机,160-240被归为中密度,240-320被归为高密度,320以上被归为超高密度(Apple给了它一个高大上的名字——Retina)
(原文地址:http://www.jianshu.com/p/af6dad66e49a)
获取苹果的设备像素比比较简单:
先规定密度分界基数为160,然后设备像素比=PPI除以密度分界基数160
1.5 DPR与PPI的关系
综合上述安卓和苹果的密度分界图,可以得到的DPR与PPI的关系如下:
DPR = PPI/160
1.6 设备像素与CSS像素之间的关系
获得设备像素比(dpr)后,便可得知设备像素与CSS像素之间的比例。当这个比率为1:1时,使用1个设备像素显示1个CSS像素。当这个比率为2:1时,使用4个设备像素显示1个CSS像素,当这个比率为3:1时,使用9(3*3)个设备像素显示1个CSS像素。
所以,有如下公式:
DPR = 设备像素/CSS像素
1.7 设备独立像素(Device independent Pixel)
也称为逻辑像素,简称dip。
根据上述设备像素与CSS像素之间的关系、及DPR的官方定义,我们可以推断出:
CSS像素 =设备独立像素 = 逻辑像素
下面,还是引用 http://www.cnblogs.com/2050/p/3877280.html 文中的内容说明:
在移动端浏览器中以及某些桌面浏览器中,window对象有一个devicePixelRatio属性,它的官方的定义为:设备物理像素和设备独立像素的比例,也就是 devicePixelRatio = 物理像素 / 独立像素。
CSS像素就可以看做是设备的独立像素,所以通过devicePixelRatio,我们可以知道该设备上一个css像素代表多少个物理像素。例如,在Retina屏的iphone上,devicePixelRatio的值为2,也就是说1个css像素相当于2个物理像素。但是要注意的是,devicePixelRatio在不同的浏览器中还存在些许的兼容性问题,所以我们现在还并不能完全信赖这个东西,具体的情况可以看下这篇文章
二 Viewport知识
关于viewport的知识,主要参阅了如下7篇博客:
PPK大神关于Viewport的三篇研究文章:
http://www.quirksmode.org/mobile/viewports2.html
http://www.quirksmode.org/mobile/viewports.html
http://www.quirksmode.org/mobile/metaviewport/#t10
以及上述三篇文章的译文:
http://weizhifeng.net/viewports2.html
http://weizhifeng.net/viewports.html
http://blog.csdn.net/aiolos1111/article/details/51919795
以及本文开头提到的博客:
http://www.cnblogs.com/2050/p/3877280.html
首先引用PPK文章中的说明来解释一下什么是Viewport
George Cummins explains the basic concept best here at Stack Overflow:
“
Imagine the layout viewport as being a large image which does not change size or shape. Now image you have a smaller frame through which you look at the large image. The small frame is surrounded by opaque material which obscures your view of all but a portion of the large image. The portion of the large image that you can see through the frame is the visual viewport. You can back away from the large image while holding your frame (zoom out) to see the entire image at once, or you can move closer (zoom in) to see only a portion. You can also change the orientation of the frame, but the size and shape of the large image (layout viewport) never changes.
”See also this explanation by Chris.
The visual viewport is the part of the page that’s currently shown on-screen. The user may scroll to change the part of the page he sees, or zoom to change the size of the visual viewport.
(原文地址:http://www.quirksmode.org/mobile/viewports2.html)
译文:
George Cummins在Stack Overflow上对基本概念给出了最佳解释:
把layout viewport想像成为一张无法改变大小或形状的大图。现在想像你有一个小一些的框架,你通过它来看这张大图。这个小框架的周围包裹着不透明材料,掩盖了你所有的视线,你只能看到这张大图的一部分。你通过这个框架所能看到的大图的一部分就是visual viewport。你可以后拉(放大)框架以观看整个图片,或者你可以靠近一些(缩小框架)只看局部。你也可以改变框架的方向,但是大图(layout viewport)的大小和形状永远不会变。Chris给出的关于Visual viewport的解释:
visual viewport是页面显示在当前屏幕上的那一部分。用户可以通过滚动来改变他所看到的页面的部分,或者通过缩放来改变visual viewport的大小。
(原文地址:http://blog.csdn.net/aiolos1111/article/details/51956691)
下面以我自己的理解解释一下什么是Viewport:
1、Viewport就是移动设备浏览器上(也可能是一个app中的webview)用来显示网页的一块“画布”。
2、移动设备上的页面是显示在Viewport上的。
3、移动设备的浏览器都有viewport元标签,而引入viewport的目的就是用于解决PC页面能在手机上正常显示,不会因屏幕变小而挤压布局导致页面排版混乱的问题。
4、在引入了Viewport概念并做如下规定后,就不会破坏那些没有针对手机浏览器优化的PC网页的布局,用户可以通过平移和缩放来看网页的其他部分。
移动设备上的layout viewport的宽永大等于可视区域(Visual viewport)的宽
(原文地址:http://www.quirksmode.org/mobile/metaviewport/#t10 )
5、PPK大神对于移动设备上的viewport有着非常多的研究,他认为移动设备上有三个viewport:layout viewport 、 visual viewport 和 ideal viewport。
下面我们分别讲解一下这三种Viewport
2.1 layout viewport(布局视口)
这是移动设备引入的第一个Viewport。引用一段我非常欣赏的话来说明layout viewport:
首先,移动设备上的浏览器认为自己必须能让所有的网站都正常显示,即使是那些不是为移动设备设计的网站。但如果以浏览器的可视区域作为默认viewport的话,因为移动设备的屏幕都不是很宽,所以那些为桌面浏览器设计的网站放到移动设备上显示时,必然会因为移动设备的viewport太窄,而挤作一团,甚至布局什么的都会乱掉。也许有人会问,现在不是有很多手机分辨率都非常大吗,比如768x1024,或者1080x1920这样,那这样的手机用来显示为桌面浏览器设计的网站是没问题的吧?前面我们已经说了,css中的1px并不是代表屏幕上的1px,你分辨率越大,css中1px代表的物理像素就会越多,devicePixelRatio的值也越大,这很好理解,因为你分辨率增大了,但屏幕尺寸并没有变大多少,必须让css中的1px代表更多的物理像素,才能让1px的东西在屏幕上的大小与那些低分辨率的设备差不多,不然就会因为太小而看不清。所以在1080x1920这样的设备上,在默认情况下,也许你只要把一个div的宽度设为300多px(视devicePixelRatio的值而定),就是满屏的宽度了。
回到正题上来,如果把移动设备上浏览器的可视区域设为viewport的话,某些网站就会因为viewport太窄而显示错乱,所以这些浏览器就决定默认情况下把viewport设为一个较宽的值,比如980px,这样的话即使是那些为桌面设计的网站也能在移动浏览器上正常显示了。ppk把这个浏览器默认的viewport叫做 layout viewport。
下图列出了一些设备上浏览器的默认layout viewport的宽度:
注:该图引用自:http://www.quirksmode.org/mobile/metaviewport/#t10
图中的数值均是合理的,没有对错之分,这个数值是由设备厂商自己决定的。
2.1.1 手机浏览器渲染网页的过程
在这里有必要说明一下手机浏览器渲染网页的过程:
Step 1: 渲染————将整个页面渲染在一个layout viewport中,以保证页面排版正确。
Step 2: 缩放————将整个layout viewport缩放到visual viewport大小,以保证页面在手机屏幕上被完整显示出来
也正是因为缩放,才会出现手机上font-size为40px与pc上font-size12px的同等物理大小的情况
2.1.2 获取layout viewport的尺寸
通过document.documentElement.clientWidth和-Height可以获取layout viewport的尺寸
兼容性:这种获取方式在Android 和IPhone手机上完全支持。
(原文地址:http://weizhifeng.net/viewports2.html)
2.2 visual viewport(可视视口)
同样引用一段我非常欣赏的话来说明visual viewport:
因为浏览器可视区域(visual viewport)的宽度比这个layout viewport的宽度要小(见第四部分<总结>第7条),带来的后果就是浏览器会出现横向滚动条,所以我们还需要一个viewport来代表浏览器可视区域的大小,ppk把这个viewport叫做 visual viewport。
2.2.1 获取visual viewport的尺寸
对于visual viewport,它是通过window.innerWidth/Height来进行度量的。很明显当用户缩小或者放大的时候,度量的尺寸会发生变化。
兼容性:IPhone上完全支持,在Android 2, Oprea mini 和 UC 8中无法正确获取。
(原文地址:http://weizhifeng.net/viewports2.html)
2.3 ideal viewport(理想视口)
再次引用一段我非常欣赏的话来说明ideal viewport:
又因为现在越来越多的网站都会为移动设备进行单独的设计,所以必须还要有一个能完美适配移动设备的viewport。所谓的完美适配指的是,首先不需要用户缩放和横向滚动条就能正常的查看网站的所有内容;第二,显示的文字的大小是合适,比如一段14px大小的文字,不会因为在一个高密度像素的屏幕里显示得太小而无法看清,理想的情况是这段14px的文字无论是在何种密度屏幕,何种分辨率下,显示出来的大小都是差不多的。当然,不只是文字,其他元素像图片什么的也是这个道理。ppk把这个viewport叫做 ideal viewport,也就是第三个viewport——移动设备的理想viewport。
ideal viewport并没有一个固定的尺寸,不同的设备拥有有不同的ideal viewport。所有的iphone的ideal viewport宽度都是320px,无论它的屏幕宽度是320还是640,也就是说,在iphone中,css中的320px就代表iphone屏幕的宽度。
但是安卓设备就比较复杂了,有320px的,有360px的,有384px的等等,关于不同的设备ideal viewport的宽度都为多少,可以到http://viewportsizes.com去查看一下,里面收集了众多设备的理想宽度。
再总结一下:ppk把移动设备上的viewport分为layout viewport 、 visual viewport 和 ideal viewport 三类,其中的ideal viewport是最适合移动设备的viewport,ideal viewport的宽度等于移动设备的屏幕宽度(即设备逻辑像素,本文作者注),只要在css中把某一元素的宽度设为ideal viewport的宽度,那么这个元素的宽度就是设备屏幕的宽度了,也就是宽度为100%的效果。ideal viewport 的意义在于,无论在何种分辨率的屏幕下,那些针对ideal viewport 而设计的网站,不需要用户手动缩放,也不需要出现横向滚动条,都可以完美的呈现给用户。
从上述描述,我们可以得到一个结论:
ideal viewport的宽度等于移动设备的屏幕宽度(这个理想的宽度是指以CSS像素单位计算的宽度,即屏幕的逻辑像素宽度),跟设备的物理宽度没有关系。在css中,这个宽度就相当于100%的所代表的那个宽度。
即有:
ideal viewport的宽度 = 屏幕的逻辑像素宽度
最后,我们通过一段引用再说说ideal viewport存在的必要性:
为什么需要有理想的viewport呢?比如一个分辨率为320x480的手机理想viewport的宽度是320px,而另一个屏幕尺寸相同但分辨率为640x960的手机的理想viewport宽度也是为320px,那为什么分辨率大的这个手机的理想宽度要跟分辨率小的那个手机的理想宽度一样呢?这是因为,只有这样才能保证同样的网站在不同分辨率的设备上看起来都是一样或差不多的。实际上,现在市面上虽然有那么多不同种类不同品牌不同分辨率的手机,但它们的理想viewport宽度归纳起来无非也就 320、360、384、400等几种,都是非常接近的,理想宽度的相近也就意味着我们针对某个设备的理想viewport而做出的网站,在其他设备上的表现也不会相差非常多甚至是表现一样的。
三 meta标签控制viewport
移动设备默认的viewport是layout viewport,但在进行移动设备网站的开发时,我们需要的是ideal viewport。那么怎么才能得到ideal viewport呢?这就该轮到meta标签出场了。
在开发移动设备的网站时,建议在head标签中使用如下代码:
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
- 1
那这段代码的作用是什么呢?
允不允许用户缩放不同的网站有不同的要求,我们不作过多说明,关键看一下width=device-width
和initial-scale=1.0
的作用:
设置 initial-scale这条规则实际上做了如下2件事:
1、将页面初始缩放因子设置为给定的值,计算出相对于ideal viewport的宽,得到visual viewport的宽。
2、设置layout viewport的宽等于刚刚计算出来的visual viewport的宽
(原文地址:http://www.quirksmode.org/mobile/metaviewport/#link15
译文地址:http://blog.csdn.net/aiolos1111/article/details/51919795 )
3、设置layout viewport的宽等于ideal viewport的宽
(原文地址:http://www.quirksmode.org/mobile/metaviewport/#link5)
译文地址:http://blog.csdn.net/aiolos1111/article/details/51919795 )
.
设置width=device-width这条规则实际上做了如下2件事:
1、将layout viewport的宽设置为设备屏幕的宽度(以CSS像素单位计算的宽度,即屏幕的逻辑像素宽度,本人注)
(原文地址:http://www.quirksmode.org/mobile/metaviewport/#link2)
2、将ideal viewport的宽设置为layout viewport的宽。(原文地址:http://www.quirksmode.org/mobile/metaviewport/#link5)
所以,综合这2条规则,知道该标签的作用是让layout viewport的宽度等于设备的屏幕宽度,再等于ideal viewport的宽度,而这也是移动WEB页面的最佳实践原则:
视图viewport的宽度 = 布局viewport的宽度 = 设备宽度(device-width)
3.1 两个问题
根据上述描述,有两个问题需要澄清一下:
3.1.1 如果不设置meta viewport标签
如果不设置meta viewport标签,那么移动设备上浏览器默认的layout viewport宽度值为980px,1024px等这些,总之是大于屏幕宽度的(这里的宽度所用的单位px都是指css中的px,它跟代表实际屏幕物理像素的px不是一回事)。
如果不设置meta viewport标签,一个PC的页面在移动设备上会进行缩放并完整显示出来!
3.1.2 为什么要用2个相同功能的规则
大家应该发现width=device-width和initial-scale=1.0的功能基本一样,那为什么都要用到呢?
我们继续引用PPK大神的话来说明:
原文地址:http://www.quirksmode.org/mobile/metaviewport/
根据上图我们可得:
width=device-width在IPhone和IPad上存在兼容问题;
initial-scale=1.0在IE上存在兼容问题
所以,
要把layout 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.0, maximum-scale=1.0, user-scalable=no">
- 1
3.2 缩放因子
上面提到了一个概念”页面初始缩放因子”,现在我们说明一下什么是缩放因子:
先给出PPK大神关于缩放因子的公式
zoom factor = ideal viewport width / visual viewport width
(PS:visual viewport的宽度指的是浏览器可视区域的宽度)
从这个公式,我们可以得到一个结论:
页面缩放是相对于ideal viewport来进行缩放的
(原文地址:http://www.quirksmode.org/mobile/metaviewport/)
四 总结
1、设备像素是设备分辨率的单位,同一个设备的设备像素大小固定不变
2、DPR = 设备像素/CSS像素 = 设备像素 / 设备独立像素 ~= PPI/160 = 页面缩放比例
2、visual viewport width = ideal viewport width / zoom factor(其中,同一个设备的ideal viewport的宽度固定不变,因此缩放页面只是改变visual viewport的大小)
3、CSS像素 = 设备独立像素 = 逻辑像素
4、同一个设备的CSS像素数字大小不变,但每CSS像素代表的长度会变,即CSS像素会伸缩
5、现代浏览器中实现缩放的方式都是「拉伸」像素:即每CSS像素单位代表的长度发生变化,而像素总数字不变。所以缩放会引起CSS像素的变化。
6、进行缩放时,visual viewport的尺寸会发生变化,layout viewport的尺寸保持不变
7、移动设备上的layout viewport的尺寸都大等于其浏览器的可视区域(visual viewport)
8、css中的1px并不是代表设备像素上的1px
9、移动设备分辨率越大,css中1px代表的物理像素就会越多,devicePixelRatio的值也越大
10、ideal viewport的宽度等于移动设备的屏幕宽度(这个理想的宽度是指以CSS像素单位计算的宽度,即屏幕的逻辑像素宽度),跟设备的物理宽度没有关系。同一个设备的ideal viewport的宽度固定不变。
11、移动端常见的操作系统及其浏览器内核如下图
12、移动端页面设计尺寸原则:因为dpr一般都是1或者2,所以设计页面时应按照设备逻辑像素的2倍大小进行设计
13、最后以三张图结束本文
a、未设置meta viewport标签时的移动端页面效果
b、设置<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0">
后的移动端页面效果
c、设置<meta name="viewport" content="width=device-width,initial-scale=1.0">
后的移动端页面效果