之前也或多或少也接触过移动端,写移动端页面的时候,总是会在head标签里加这么一行代码
<meta name="viewport" content="width=device-width, initial-scale=1" />
不管知不知道背后的原理,反正加这么一句话后,网页宽度就与屏幕宽度完美一致了。直到最近做的一个项目,需要将已经写好的PC页面再重构一份移动端页面,意外的发现,原来PC上的页面在手机上布局没有乱,而且没有出现滚动条,然后我加上了上面那句代码,滚动条又出现了,我想是时候真正认识一下viewport了。
而在理解viewport的时候,看了大量的博客,越看越糊涂,最后综合多人的博客,才得出自己的理解,而在理解viewport之前,先要理解下面这五点
1.屏幕分辨率
屏幕分辨率:屏幕分辨率是一个物理属性,表示一个屏幕上有多少个像素点,如iphone 6 的分辨率是1334px ×750px,表示屏幕可以分成1334*750个像素点。
2.屏幕尺寸
这个很容易理解,只需要知道我们说的手机5.5寸屏,说的是对角线的长度。
3.屏幕像素密度 dpi/ppi
每单位尺寸上,有多少个物理像素点。一个手机给你,屏幕分辨率是固定的,屏幕的尺寸是固定,所以屏幕像素密度也是固定的。
4.css像素
css像素不是绝对单位,是相对单位。在PC上,1px与1物理像素是一致的,所以如果你的笔记本屏幕分辨率是1366px x 768px 的,你给body width:1366px,刚好撑满屏幕。但事实上css里的1px并不总是等于1物理像素。在移动端,如iphone3,它的分辨率为320x480,在iphone3上,一个css像素确实是等于一个屏幕物理像素的。后来随着技术的发展,移动设备的屏幕像素密度越来越高,从iphone4开始,苹果公司便推出了所谓的Retina屏,分辨率提高了一倍,变成640x960,但屏幕尺寸却没变化,这就意味着同样大小的屏幕上,像素却多了一倍,这时,一个css像素是等于两个物理像素的。此外,屏幕缩放也会影响到这个关系。
5.device-width(这里的width是csspx)
这个东西,曾经困扰了我很久,单单去理解viewport,并不是很复杂,但是当你决定要把一系列知识搞清楚的时候,任何一个环节想不通都会让你抓狂。device-width从字面意思上即设备宽度,但是iphone 6的分辨率为1344px750px,而iphone 6的device-width为375px,iphone 5的device-width为320px,很明显device-width与分辨率不是一比一的关系,那么它与移动设备的物理像素,尺寸,单位像素密度又何关系呢?在回答这个问题之前,我们先想,如果device-width与物理像素一致会发生什么?
iphone 3的分辨率320px480px,iphone 4的分辨率翻了一倍,但是iphone 3和iphone 4的尺寸却是一样的。所以如果device-width与物理像素为1:1的关系,那么原来为iphone 3开发的网页中,有一个100px的div,大约占了屏幕的1/3,而在iphone 4上,只占了屏幕的大约1/6,这显然不行,原来满屏的东西,在iPhone4上只占了一半。所以现在就要解决这个问题
方案1.:再为iphone4写一套css,原来100px的东西,现在写200px
方案2 :既然屏幕尺寸没变,那就device-width也不变,保持320px.显然此时1px等于2个物理像素
经过简单分析,我们应该采取方案二。因为移动端的一个很大特点就是手机分辨率五花八门,按照方案1,岂不是要为每一种写一套,而且分辨率的变化程度远大于屏幕尺寸的变化程度,如上iphon3与iphone4.对于俩个尺寸大小差不多的手机,同一个东西大小看起来就差了很多,用户体验就会很不好。所以我们想要实现的一个效果就是100px的东西,在尺寸差不多大的设备上看起来都差不多大,
那么device-width应该多大呢?接下来,我们具体的看一下device-width应指是如何计算出来的。
根据设备的dpi,对应着一个转换系数(以屏幕分辨率宽度=device-width=320px的设备为标准),如iphone4 dpi对应的的转换系数为2,所以iphone 4的device-width=640px/2=320px,iphone 6的转换系数也为2,device-width=750px/2=375px.假设,折转换系数为m,则1csspx等于m倍的物理像素,这里转换系数都是依据dpi的,不能仅根据物理像素的比例关系,因为iphone3和iphone4的尺寸刚好一样,如果iphone4的屏幕分辨率扩了一倍,而尺寸也扩大了一倍,那么在刚才device-width=物理像素的假设为真时,100px的东西在iphone4与iphone 3的大小应该是一致的,所以尺寸的变化也会影响到这个比例关系,所以同时考虑物理像素和屏幕尺寸不好比较,所以统一用dpi,就没这个问题了。
6 viewport
终于到了神秘的viewport,按照前面的理解思路,理解下面的viewport的要很容易了。如果这个世界上没有电脑,只有手机,上面通过理解device-width,以及1csspx与物理像素的关系,对开发移动网页就够了,通过转换系数。设备分辨率想必物理分辨率的种类已经少了很多,基本就320,360,375,414这些。但是很明显,电脑出现的比手机要早的多,前几年开发的时候,我们基本不考虑移动端。现在不一样了,甚至有时候移动端比PC端都要重要。
这样一来,对于原来在电脑上的页面(没有做移动端处理),在手机上打开会肯定会出现滚动条,比如在pc上500px的东西,在iphone4的满屏才320px,所以肯定会出现滚动条,而特别时对于基于浮动的布局,整个页面都会乱掉。
所以手机浏览器上提出了viewport,网页是放在viewport之上的,而给它一个默认的很大宽度的值,很多设备是980px,这样原来在pc上的页面在移动端布局就不会乱掉,然后正如开头提到的,甚至连滚动条都没有。(这也是一个让我困惑过的地方)因为按照上面的理解,此时应该会出现滚动条,但是对pc端容器小于980px的布局基本不乱,后来发现的确应该是这样。如果你不加meta标签那句代码,浏览器会自动缩放,缩放到让其不出现滚动条,这也是为什么东西看起来都那么小的原因,但是如果你显示的这样设置
<meta name="viewport" content="width=980, initial-scale=1" />
网页就会出现滚动条,而如果一个div的宽度刚好与device-width一样宽,那么这个div刚好占满手机的一屏。但是仍然会出现滚动条,这个现象就像,在pc端,你的屏幕分辨率宽1366px,那么一个1366px的div会满屏,但是如果你把浏览器缩小后,这个div仍是1366px,但是可视区域小与1366px了,通过拖动滚动条,你可以看到完整的东西。
所以当我们将viewport的width设置为device-width时候,网页宽度就与设备宽度一致,html/body是继承viewport的宽度,而不是device-width。
接下来,我们简单说下关于viewport自己的东西,据很多博客主解释,viewport其实有三个,一个layout-viewport,我们meta标签设置的也是layout-viewport,还有一个visual-viewport,还有一个ideal-viewport,就是layout-viewport等于device-width的时候。关于这个viewport深层次的理解,可以参考这里。
其实理解到这里,到底有几个viewport,对我们已经不是很重要了,我们只需只道手机浏览器是把网页放在viewport上的,viewport不管你设不设置,都客观存在。
所以,移动端开发必须加加入开头我提到的那段代码,让你的网页宽度与屏幕保持一致。一个好的设计就像这样,背后包含了大量的知识,但是用户用它的时候,自然到不需要了解它背后的原理。