viewport是什么?
一般来说,在移动浏览器上页面渲染是在一个叫viewport的页面绘制区域内。
手机浏览器把页面放在一个虚拟的“窗口”(viewport)中,通常这个虚拟的“窗口”(viewport)比屏幕宽,这样就不用把每个网页挤到很小的窗口中(这样会破坏没有针对手机浏览器优化的网页的布局),用户可以通过平移和缩放来看网页的不同部分。
- layout viewport:是网页的所有内容,他可以全部或者部分展示给用户。
- visual viewport:是当前显示给用户内容的窗口,你可以拖动或者放大缩小网页。
viewport和屏幕的真实尺寸并不是对应的,如在Safari Mobile中viewport默认宽度(320px)是屏幕真实尺寸(640px)的一半,这里不管是用window.innerHeight还是window.screen.width拿到的都是320px。
当然我们可以通过meta设置改变viewport的比例,如initial-scale=.5就可以让viewport和屏幕一致的尺寸,这个比例在不同的手机上并不一定是2倍关系,特别是Android手机。而且改变viewport比例后可能会导致后续制作中出现一系列问题。另外Android系统中可以在viewport设置target-densitydpi=device-dpi让viewport的尺寸和屏幕真实尺寸保持一致,但iOS不起作用,所以这个方法不具有普遍性。不要纠结一定要拿到屏幕真实尺寸,就把viewport的尺寸当成屏幕的尺寸进行页面设计和制作肯定是没有问题的。
例如:当你打开一个960px设计的网页时,手机会根据css中的百分比进行缩放。比如总长960的页面,导航条是20%。(实际解析出来就是192px)但是你不可能每个属性都是百分比吧,比如文字大小。那么我用320px屏幕打开,导航条就成了64px了,但是我的字体大小是12px啊,完了,本来能显示很多汉字的(192/12)现在只能显示64/12个汉字了。
Apple找到了一个办法:在移动版(iOS)的Safari中定义了viewport meta标签①,它的作用就是创建一个虚拟的窗口(viewport),而且这个虚拟窗口的分辨率接近于桌面显示器,Apple将其定位为980px②。
①除此之外不同移动浏览器厂商也有不同的解决方案,例如UCweb就是使用中间件技术。
②不同的浏览器厂商对于layout viewport的大小定义不同
Safari iPhone: 980px Opera: 850px Android WebKit: 800px IE: 974px
一、基本概念
首先,viewport指视口,浏览器上(或一个app中的webview)显示网页的区域。PC端的视口是浏览器窗口区域,而移动端的则存在三个不同的视口:
layout viewport:布局视口
visual viewport:视觉视口
ideal viewport:理想视口
1. layout viewport 布局视口
在PC端的网页的layout viewport即浏览器页面显示的整个区域,也可以理解成网页的绘制区域。而在移动端由于其屏幕较小,无法全部显示PC端页面的全部内容,所以默认情况下(不用<meta name="viewport">去控制),移动端会指定一个大于其浏览器显示区域layout viewport,一般是980px,如下图所示:
图1
在chrome浏览器上的实验结果,未进行视口控制的页面的默认宽度为980px,即页面在宽度为980px的页面上进行了绘制。
2. visual viewport 视觉视口
visual viewport,顾名思义指浏览器可视区域,即我们在移动端设备上看到的区域。为了区别其和layout viewport的区别,我们看一下下面的图:
layout viewport:
visual viewport:
网页的实际绘制区域视口大小layout viewport比我们在手机上可以看到的大小要大,所以我们手机端视觉视口会出现横向滚动条。
3. ideal viewport 理想视口
所谓理想视口,即页面绘制区域可以完美适配设备宽度的视口大小,不需要出现滚动条即可正常查看网站的所有内容,且文字图片清晰,如所有iphone的理想视口宽度都为320px,安卓设备的理想视口有320px、360px等等。
二、视口的控制
如何进行视口的控制以进行移动端页面适配呢?
我们自然想到,在移动端开发时都会在开头加上这样一行内容用于移动端页面的适配:
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
1
这行代码即用来控制viewport,其中的参数有以下几个:
参数 含义
width 设置layout viewport的宽度,为一个正整数,或字符串"width-device"
initial-scale 设置页面的初始缩放值,为一个数字,可以带小数
minimum-scale 允许用户的最小缩放值,为一个数字,可以带小数
maximum-scale 允许用户的最大缩放值,为一个数字,可以带小数
height 设置layout viewport 的高度,这个属性对我们并不重要,很少使用
user-scalable 是否允许用户进行缩放,值为"no"或"yes", no 代表不允许,yes代表允许
下面重点谈一下width和initial-scale
1. width
width用来设置layout viewport的宽度,即页面具体绘制区域的宽度,在不使用<meta>进行控制视口时,以iphone为例,其会设置视口宽度为980px。
另外width可设置为width-device字符串,表示设置视口宽度为设备的ideal viewport,如在iphone上为320px。
2. initial-scale
指页面初始的缩放值,其值可以通过如下公式进行计算:
initial-scale = ideal viewport / visual viewport
1
如initial-scale值为2,ideal viewport值为320px,则visual viewport即为160px,如下图所示,我们设置viewport为:
<meta name="viewport" content="width=device-width,initial-scale=2.0,user-scalable=no">
1
由于visual viewport小于layout viewport,横向出现滚动条,通过下方375px的div可以看出,visual viewport正好为ideal viewport的一半
关于initial scale的默认值
关于initial scale,在没有使用<meta>标签时,它的值并不为1,以iphone为例,如图1中的情况
当我们没有使用<meta>标签时,其layout viewport为980px,但同时我们的可视区域即visual viewport也为980px,正好完全显示了所有的内容,可以通过公式计算此时的initial scale为:
ideal viewport / visual viewport = 320 / 980 = 0.33
1
所以当没有设置时,iniatal scale并不为1
另外,经过对iphone和ipad等ios设备的测试,不管width设置为多宽,设备都会自动计算你的initial scale值,以使得整个屏幕正好可以容纳整个页面不出现滚动条。如下所示:
物理像素:
即分辨率 设备像素又称物理像素(physical pixel),设备能控制显示的最小单位,我们可以把这些像素看作成显示器上一个个的点。 (显示)分辨率就是屏幕上显示的像素个数,分辨率160×128的意思是水平像素数为160个,垂直像素数128个。 分辨率越高,像素的数目越多,感应到的图像越精密。 而在屏幕尺寸一样的情况下,分辨率越高,显示效果就越精细和细腻。 以分辨率为1024×768的屏幕来说,即每一条水平线上包含有1024个像素点,共有768条线,即扫描列数为1024列,行数为768行。 分辨率不仅与显示尺寸有关,还受显像管点距、视频带宽等因素的影响。其中,它和刷新频率的关系比较密切,严格地说,只有当刷新频率为“无闪烁刷新频率”,显示器能达到最高多少分辨率,才能称这个显示器的最高分辨率为多少。 screen.height //screen.width返回显示设备的信息。 除非调整显示设备的分辨率,否则看作是常量。
CSS像素
CSS像素是Web编程的概念,独立于设备的用于逻辑上衡量像素的单位,也就是说我们在做网页时用到的CSS像素单位,是抽象的,而不是实际存在的。
PPI(pixels per inch)
pixels per inch所表示的是每英寸所拥有的像素(pixel)数目。
手机屏幕的PPI当达到一定数值时,人眼就分辨不出颗粒感了。
这个数值是多少?按照2010年前苹果公司CEO史蒂夫·乔布斯(Steve Jobs)在iPhone 4发布会上对视网膜技术的介绍:“当你所拿的东西距离你10-12英寸(约25-30厘米)时,它的分辨率只要达到300ppi这个‘神奇数字’(每英寸300个像素点)以上,你的视网膜就无法分辨出像素点了。”(即所谓的retina视网膜屏幕。之所以叫做视网膜屏幕,是因为屏幕的PPI(屏幕像素密度)太高,人的视网膜无法分辨出屏幕上的像素点。)
那么,是不是屏幕PPI超过这个数值就没有意义了?
==>除PPI之外,还看它的饱和度,渲染度。
有尺寸和分辨率,怎么算出来屏幕的ppi是多少?
设分辨率1920 X 1024,设长L X 宽W,
则 1920/L, 或1024/W,去两者的低数值
ppi=pixel per inch, 每英寸的像素数。
PPI即每英寸所拥有的像素数目。pixels per inch所表示的是每英寸所拥有的像素(pixel)数目。
其实计算方法很简单,用长跟高的像素数计算出对角方向的像素数(直角三角形),然后再用对角的像素数除以屏幕尺寸就是ppi了,公式表达为 PPI=√(X^2+Y^2)/ Z (X:长度像素数;Y:宽度像素数;Z:屏幕大小)。
DPR设备像素比
DPR(devicePixelRatio)是默认缩放为100%的情况下,设备像素和CSS像素的比值:
DPR = 设备像素 / CSS像素(某一方向上)
普通密度桌面显示屏的devicePixelRatio=1
高密度桌面显示屏(Mac Retina)的devicePixelRatio=2
主流手机显示屏的devicePixelRatio=2或3
因为大部分桌面显示器的devicePixelRatio为1,所以在PC端我们感受不出来CSS Pixel 与 物理像素的差别。
举个栗子来说,一张100x100的图片,通过CSS设置它width:100px; height:100px; 。在电脑上打开,没有什么问题,但是在手机上打开,屏幕按照逻辑分辨率来渲染,假设手机的devicePixelRatio=3,那么就相当于拿3个物理像素来描绘1个电子像素。这等于拿一个三倍的放大镜去看你的图片,你的图片可能因此变得模糊,因为细节不够。所以一般明智的做法是把图片换成300x300的,CSS宽高不变,这样在手机上展示时,CSS宽高换算成物理像素是300x300,你的图片也是300x300,就不会变糊了。