这里我得盗一下图,来好好说说这些概念
简单的说就是你的显示器的分辨率用物理像素描述的,而横向和纵向的分辨率值可以用screen.width/height打印出来。它们是显示器的功能,而不是浏览器的功能。不管窗口放大缩小,screen.width/height是不会变的。(IE7、8是例外,均以CSS像素为单位进行测量)。除非设置分辨率,让LED液晶板重新划分物理像素点,否则就认为分辨率不变。
浏览器窗口里面的宽度和高度可以用window.innerWidth/innerHeight描述,单位是CSS像素。
既然说是CSS像素,肯定缩放之后会有变化,如图
Console窗口的改变相当于改变浏览器显示大小。如果放大,窗口中的可用空间会减少,并 window.innerWidth/Height
通过减少来反映出来。(Opera是一个例外,Opera window.innerWidth/Height
不会在用户放大时减小:它们以设备像素为单位进行度量。这在台式机上很烦人,但在移动设备上却很致命)
注意:测量的宽度和高度包括滚动条。它们也被视为内部窗口的一部分,这主要是出于历史原因。
移动设备上的viewport就是设备的屏幕上能用来显示我们的网页的那一块区域,在具体一点,就是浏览器上(也可能是一个app中的webview)用来显示网页的那部分区域,但viewport又不局限于浏览器可视区域的大小,它可能比浏览器的可视区域要大,也可能比浏览器的可视区域要小。
如果有这么一个页面,PC端显示如下,图片大小是200px*200px(CSS像素)
移动端
我们打开标尺Show rulers发现,物理视口的物理像素是375px。若不清楚物理像素和CSS像素可见前篇图文并茂带你弄懂分辨率、物理像素、逻辑像素、dpr、ppi
它将PC页面缩小到一个手机屏幕的可视范围,原理是怎么样的呢?我们用下面的图来说说
移动设备上的浏览器都会把自己默认的viewport设为980px或1024px(也可能是其它值,这个是由设备自己决定的),这里是980px。这个是CSS像素。横向980个CSS像素必须显示在横向375个物理像素点上。这样1个物理像素在横向上不得不显示980/375≈2.61个CSS像素,所以1个物理像素显示2.61×2.61个CSS像素,也就是我们看到的缩小效果。缩小之后一个物理像素现在重叠了2.61*2.61≈6.8个CSS像素,强行缩小显示在移动端,看起来会太小,体验很不友好。
现在我们加上meta标签<meta name="viewport" content="initial-scale=1">,初始缩放比为1(等于没有缩放),比如iphone6 的初始宽度的物理像素为375px,1CSS像素占1个物理像素,所以CSS像素最大显示也是375px。
下图是显示200px×200px(CSS像素)的图片,在缩放比为1的显示情况。
右下角盒子模型中的像素是CSS像素,切记
我们改为<meta name="viewport" content="initial-scale=2">,现在缩放比是2,缩放的是CSS像素。我要好好说说这个例子。
原来1个CSS像素表示1个物理像素,此时横向上1个CSS像素表示2个物理像素。以横向为例,看起来被截断了,要显示完整宽度需要视口宽度是400px(物理像素),这里只有375个物理像素点,故被"截断"。
横向的解释:可以看到因为放到了2倍,所以横向的375px变为了187.5px(取整为187),也就是说原来横向375个物理像素点需要375个CSS像素点,现在375个物理像素点只需要187个CSS像素点就可以覆盖,横向1个CSS像素就覆盖了2个物理像素点。
纵向的解释:纵向也是放大2倍,原来缩放比为1的时候纵向只需要290个物理像素,现在纵向需要580个物理像素,纵向的1个CSS像素覆盖了2个物理像素点。这里html的高度(CSS像素)始终是290px,放大后CSS像素没变,而纵向覆盖的物理像素变成了2倍。
<meta name="viewport" content="initial-scale=0.5">初始缩放比为0.5
如果初始缩放比为1,那么布局的宽度就是和视口viewport的宽度是一样的,即initial-scale=1等同于width=device-width的效果
缩放比为1--->单方向上,1物理像素用1CSS像素覆盖
缩放比为0.5 --->单方向上,1物理像素用2CSS像素覆盖
所以图片的宽度是200个CSS像素,只覆盖了100个物理像素,高度也是一样。
initial-scale=1其实和width=device-width效果虽然是一样的,但是如果只写一个,在不同的浏览器可能会出现bug,所以为了兼容性,把这2个都写上
<meta name="viewport" content="width=device-width, initial-scale=1">
initial-scale=1 解决了 iphone、ipad的横竖屏不区分毛病,width=device-width则解决了IE的横竖屏不区分毛病
而这里的例子,视口宽度是375个物理像素,所以,width=375也和width=device-width效果一样,即
<meta name="viewport" content="width=375">等同于
<meta name="viewport" content="width=device-width">
但是为了适应各种设备,还是要写成width=device-width
一般来说,我们在移动端是不让用户缩放的。
现在混合Hybrid app那么多,为了看起来更像原生开发,也不会让用户缩放,如果不让缩放,看起来是原生开发,如果用户能缩放,一看就是网页,体验不好,有可能和手机的快捷手势冲突
那么不让缩放可以有2种写法
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
最大缩放比为1,最小缩放比为1
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
不允许用户缩放(IOS的safari中,即使你写的 user-scalable=no,用户照样可以缩放)
同样的,为了保证兼容性,把三者都写上
最后视口最标准的写法如下
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no, maximum-scale=1, minimum-scale=1">
width | 设置布局视口的宽度,为一个正整数,不要加px单位,或字符串"width-device" |
---|---|
initial-scale | 设置页面的初始缩放值,为一个数字,可以带小数 |
minimum-scale | 允许用户的最小缩放值,为一个数字,可以带小数 |
maximum-scale | 允许用户的最大缩放值,为一个数字,可以带小数 |
height | 设置布局视口的高度,请忽略,基本没用过 |
user-scalable | 是否允许用户进行缩放,值为"no"或"yes", no 代表不允许,yes代表允许 |
PC端
一般讨论视口就是说移动端,和PC端无关,但是这里还是说一下效果
PC端的 window.innerWidth 和 document.documentElement.clientWidth 打印的是显示宽度(CSS像素),缩放就看得到区别,验证是CSS像素
没做视口viewport适配的显示效果
做了视口适配的效果(比如百度)
兼容性的方案:
var viewWidth = document.documentElement.clientWidth || window.innerWidth;
即可获取视口宽度,如果做了视口适配,这个打印出来就是和屏幕宽度一样的值,比如这里的375个CSS像素,如果不做视口适配,这个打印出来就是默认视口宽度(和机型相关),比如980个CSS像素
配套演示代码可自行下载调试
https://gitee.com/lcy0515/viewport/
或 https://download.csdn.net/download/qq_34115899/12379615
参考文章: