一、viewport概念
移动设备上的viewport就是设备的屏幕上能用来显示我们的网页的那一块区域,viewport不局限于浏览器可视区域的大小,它可能比浏览器的可视区域要大,也可能比浏览器的可视区域要小。
一般来讲,移动设备上的viewport都是要大于浏览器可视区域的,这是因为考虑到移动设备的分辨率相对于桌面电脑来说都比较小,所以为了能在移动设备上正常显示那些传统的为桌面浏览器设计的网站,移动设备上的浏览器都会把自己默认的viewport设为980px或1024px(也可能是其它值,这个是由设备自己决定的),但带来的后果就是浏览器会出现横向滚动条,因为浏览器可视区域的宽度是比这个默认的viewport的宽度要小的。
二、css中的1px
在css中我们一般使用px作为单位,在桌面浏览器中css的1个像素往往都是对应着电脑屏幕的1个物理像素。但css中的像素只是一个抽象的单位,在不同的设备或不同的环境中,css中的1px所代表的设备物理像素是不同的。
还有一个因素也会引起css中px的变化,那就是用户缩放。例如,当用户把页面放大一倍,那么css中1px所代表的物理像素也会增加一倍;反之把页面缩小一倍,css中1px所代表的物理像素也会减少一倍。
在移动端浏览器中以及某些桌面浏览器中,window对象有一个devicePixelRatio属性,它的官方的定义为:设备物理像素和设备独立像素的比例,也就是 devicePixelRatio = 物理像素 / 独立像素
。css中的px就可以看做是设备的独立像素,所以通过devicePixelRatio,我们可以知道该设备上一个css像素代表多少个物理像素。
三、三个viewport理论
ppk认为,移动设备上有三个viewport。
如果把移动设备上浏览器的可视区域设为viewport的话,某些网站就会因为viewport太窄而显示错乱,所以这些浏览器就决定默认情况下把viewport设为一个较宽的值,比如980px,这样的话即使是那些为桌面设计的网站也能在移动浏览器上正常显示了。ppk把这个浏览器默认的viewport叫做 layout viewport,宽度可以通过 document.documentElement.clientWidth
来获取。
然而,layout viewport 的宽度是大于浏览器可视区域的宽度的,所以我们还需要一个viewport来代表浏览器可视区域的大小,ppk把这个viewport叫做 visual viewport,宽度可以通过window.innerWidth
来获取。
现在越来越多的网站都会为移动设备进行单独的设计,所以必须还要有一个能完美适配移动设备的viewport。所谓的 完美适配 指的是,首先不需要用户缩放和横向滚动条就能正常的查看网站的所有内容;第二,显示的文字的大小是合适,比如一段14px大小的文字,不会因为在一个高密度像素的屏幕里显示得太小而无法看清,理想的情况是这段14px的文字无论是在何种密度屏幕,何种分辨率下,显示出来的大小都是差不多的。当然,不只是文字,其他元素像图片什么的也是这个道理。ppk把这个viewport叫做ideal viewport,也就是第三个viewport——移动设备的理想viewport。
ideal viewport 并没有一个固定的尺寸,不同的设备拥有有不同的 ideal viewport。
ideal viewport 的意义在于,无论在何种分辨率的屏幕下,那些针对ideal viewport 而设计的网站,不需要用户手动缩放,也不需要出现横向滚动条,都可以完美的呈现给用户。
四、meta标签控制viewport
meta标签示例:
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
五、把当前的viewport宽度设置为 ideal viewport 的宽度
- 要得到ideal viewport就必须把默认的layout viewport的宽度设为移动设备的屏幕宽度。因为meta viewport中的width能控制layout viewport的宽度,所以我们只需要把width设为width-device这个特殊的值就行了。
<meta name="viewport" content="width=device-width">
可以看到通过width=device-width
,所有浏览器都能把当前的viewport宽度变成ideal viewport的宽度。
缺点是在iphone和ipad上,无论是竖屏还是横屏,宽度都是竖屏时ideal viewport的宽度。
- 利用缩放也可以达到同样的效果。缩放是相对于 ideal viewport来进行缩放的,当对ideal viewport进行100%的缩放,也就是缩放值为1的时候,就得到了 ideal viewport。
<meta name="viewport" content="initial-scale=1">
缺点是windows phone 上的IE 无论是竖屏还是横屏都把宽度设为竖屏时ideal viewport的宽度。
- 如果
width
和initial-scale=1
同时出现,并且还出现了冲突呢?例如:
<meta name="viewport" content="width=400, initial-scale=1">
当遇到这种情况时,浏览器会取它们两个中较大的那个值。
总结:要把当前的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">
六、关于meta viewport的更多知识
- 缩放:缩放是相对于ideal viewport来缩放的,缩放值越大,当前viewport的宽度就会越小,反之亦然。
visual viewport宽度 = ideal viewport宽度 / 当前缩放值
当前缩放值 = ideal viewport宽度 / visual viewport宽度
-
initial-scale
的默认值
- 安卓设备上的initial-scale默认值好像没有方法能够得到,或者就是干脆它就没有默认值,一定要你显示的写出来这个东西才会起作用。
- 在iphone和ipad上,无论你给layout viewport设置的宽度是多少,而又没有指定初始的缩放值的话,那么iphone和ipad会自动计算
initial-scale
这个值,以保证当前layout 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>
七、结语
- 如果不设置meta viewport标签,那么移动设备上浏览器默认的宽度值为800px,980px,1024px等这些,总之是大于屏幕宽度的。这里的宽度所用的单位px都是指css中的px,它跟代表实际屏幕物理像素的px不是一回事。
- 每个移动设备浏览器中都有一个理想的宽度,这个理想的宽度是指css中的宽度,跟设备的物理宽度没有关系。在css中,这个宽度就相当于100%的所代表的那个宽度。我们可以用meta标签把viewport的宽度设为理想宽度,如果不知道这个设备的理想宽度是多少,那么用
device-width
这个特殊值就行了,同时initial-scale=1
也有把viewport的宽度设为理想宽度的作用。所以,我们可以使用以下mate标签写法来得到一个理想的viewport(也就是前面说的ideal viewport
)。
<meta name="viewport" content="width=device-width, initial-scale=1">
-
ideal viewport
保证同样的网站在不同分辨率的设备上看起来都是一样或差不多的。
参考链接:viewport 深入理解
原文:移动前端开发之viewport的深入理解