前言:正好最近有时间,给移动端适配这里做一个整理,全面并且深入地重新去理解这些代码的含义,不再只是代码的搬运工,不再只会像之前一样复制粘贴~~
关键词:移动端适配,meta viewport~~......
正文:
一、基本定义
:Viewport 视窗,视口。通俗的讲,viewport是用户网页的可视区域。移动设备上的viewport就是设备的屏幕上能用来显示我们的网页的那一块区域,具体来说,就是浏览器上用来显示网页的那部分区域,但viewport又不局限于浏览器可视区域的大小,它可能比浏览器的可视区域要大,也可能比浏览器的可视区域要小。个人觉得,说白了,上面那一大坨无非说的就是你能看到的网页的那部分,它可大可小。
二、css中的1px并不等于设备的1px
在css中我们一般使用px作为单位,在桌面浏览器中css的1个像素往往都是对应着电脑屏幕的1个物理像素,这可能会造成我们的一个错觉,那就是css中的像素就是设备的物理像素。但实际情况却并非如此,css中的像素只是一个抽象的单位,在不同的设备或不同的环境中,css中的1px所代表的设备物理像素是不同的。在为桌面浏览器设计的网页中,我们无需对这个津津计较,但在移动设备上,必须弄明白这点。
还有一个因素也会引起css中px的变化,那就是用户缩放。例如,当用户把页面放大一倍,那么css中1px所代表的物理像素也会增加一倍;反之把页面缩小一倍,css中1px所代表的物理像素也会减少一倍。
也就是说,在不同的设备或不同的环境中或者当用户缩放时,css中的1px并不等于设备的1px。
三、移动设备上的三个viewport
移动设备上有三个viewport,为什么会有三个viewport:
先说些题外话:首先,移动设备上的浏览器认为自己必须能让所有的网站都正常显示,即使是那些不是为移动设备设计的网站。但如果以浏览器的可视区域作为viewport的话,因为移动设备的屏幕都不是很宽,所以那些为桌面浏览器设计的网站放到移动设备上显示时,必然会因为移动设备的viewport太窄,而挤作一团,甚至布局什么的都会乱掉。
layout viewport:浏览器就决定默认情况下把viewport设为一个较宽的值,比如980px,这样的话即使是那些为桌面设计的网站也能在移动浏览器上正常显示了。这个浏览器默认的viewport就叫做 layout viewport。这个layout viewport的宽度可以通过 document.documentElement.clientWidth 来获取。
visual viewport:然而,layout viewport 的宽度是大于浏览器可视区域的宽度的,所以我们还需要一个viewport来代表 浏览器可视区域的大小,这个viewport叫做 visual viewport。visual viewport的宽度可以通过window.innerWidth 来获取,但在Android 2, Oprea mini 和 UC 8中无法正确获取。
ideal viewport:因为现在越来越多的网站都会为移动设备进行单独的设计,所以必须还要有一个能完美适配移动设备的viewport。所谓的完美适配指的是:
- 第一,不需要用户缩放和横向滚动条就能正常的查看网站的所有内容;
- 第二,显示的文字的大小是合适,比如一段14px大小的文字,不会因为在一个高密度像素的屏幕里显示得太小而无法看清,理想的情况是这段14px的文字无论是在何种密度屏幕,何种分辨率下,显示出来的大小都是差不多的。
- 第三,不只是文字,其他元素像图片什么的也是这个道理。
这个viewport叫做ideal viewport,也就是第三个viewport——移动设备的理想viewport。ideal viewport并没有一个固定的尺寸,不同的设备拥有有不同的ideal viewport。所有的iphone的ideal viewport宽度都是320px,无论它的屏幕宽度是320还是640,也就是说,在iphone中,css中的320px就代表iphone屏幕的宽度。
疑问解答:
也许有人会问,现在不是有很多手机分辨率都非常大吗,比如768x1024,或者1080x1920这样,那这样的手机用来显示为桌面浏览器设计的网站是没问题的吧?前面我们已经说了,css中的1px并不是代表屏幕上的1px,你分辨率越大,css中1px代表的物理像素就会越多,这很好理解,因为你分辨率增大了,但屏幕尺寸并没有变大多少,必须让css中的1px代表更多的物理像素,才能让1px的东西在屏幕上的大小与那些低分辨率的设备差不多,不然就会因为太小而看不清。所以在1080x1920这样的设备上,在默认情况下,也许你只要把一个div的宽度设为300多px(视devicePixelRatio的值而定),就是满屏的宽度了。
三、利用meta标签对viewport进行控制
我们在开发移动设备的网站时,最常见的的一个动作就是把下面这个东西复制到我们的head标签中:
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
该meta标签的作用是让当前viewport的宽度等于设备的宽度,同时不允许用户手动缩放。也许允不允许用户缩放不同的网站有不同的要求,但让viewport的宽度等于设备的宽度,这个应该是大家都想要的效果,如果你不这样的设定的话,那就会使用那个比屏幕宽的默认viewport,也就是说会出现横向滚动条。
meta viewport 有6个属性(content中的那些),如下:
四、把当前的viewport宽度设置为 ideal viewport 的宽度
方法一:要得到ideal viewport就必须把默认的layout viewport的宽度设为移动设备的屏幕宽度。所以我们只需要把width设为width-device这个特殊的值就行了。注意:在iphone和ipad上,无论是竖屏还是横屏,宽度都是竖屏时ideal viewport的宽度。
<meta name="viewport" content="width=device-width">
方法二:从理论上来讲,这句代码的作用只是不对当前的页面进行缩放,也就是页面本该是多大就是多大,而且缩放是相对于 ideal viewport来进行缩放的,当对ideal viewport进行100%的缩放,也就是缩放值为1的时候,就得到了 ideal viewport。缩放值越大,当前viewport的宽度就会越小。但这次轮到了windows phone 上的IE 无论是竖屏还是横屏都把宽度设为竖屏时ideal viewport的宽度
<meta name="viewport" content="initial-scale=1">
综上,所以我们经常把它们两个放在一起写。
注意:当出现如下情况:width 和 initial-scale=1同时出现,并且还出现了冲突,
<meta name="viewport" content="width=400, initial-scale=1">
当遇到这种情况时,浏览器会取它们两个中较大的那个值。例如,当width=400,ideal viewport的宽度为320时,取的是400;当width=400, ideal viewport的宽度为480时,取的是ideal viewport的宽度。
在uc9浏览器中,当initial-scale=1时,无论width属性的值为多少,此时viewport的宽度永远都是ideal viewport的宽度)
五、关于缩放动态改变meta viewport标签
首先我们先来讨论一下缩放的问题,前面已经提到过,缩放是相对于ideal viewport来缩放的,缩放值越大,当前viewport的宽度就会越小,反之亦然。例如在iphone中,ideal viewport的宽度是320px,如果我们设置 initial-scale=2 ,此时viewport的宽度会变为只有160px了,这也好理解,放大了一倍嘛,就是原来1px的东西变成2px了,但是1px变为2px并不是把原来的320px变为640px了,而是在实际宽度不变的情况下,1px变得跟原来的2px的长度一样了,所以放大2倍后原来需要320px才能填满的宽度现在只需要160px就做到了。因此,我们可以得出一个公式:
visual viewport宽度 = ideal viewport宽度 / 当前缩放值
当前缩放值 = ideal viewport宽度 / visual viewport宽度
-
在iphone和ipad上,无论你给viewport设的宽的是多少,如果没有指定默认的缩放值,则iphone和ipad会自动计算这个缩放值,以达到当前页面不会出现横向滚动条(或者说viewport的宽度就是屏幕的宽度)的目的。
五、动态改变meta viewport标签
第一种方法:可以使用document.write来动态输出meta viewport标签,例如:
document.write('<meta name="viewport" content="width=device-width,initial-scale=1">')
第二种方法:通过setAttribute来改变
<meta id="testViewport" name="viewport" content="width = 380">
<script>
var mvp = document.getElementById('testViewport');
mvp.setAttribute('content','width=480');
</script>
参考资料:
移动前端开发之viewport的深入理解:https://www.cnblogs.com/2050/p/3877280.html