先上结论:
pc版页面:不需要设置viewport ,手机上会缩放到合适大小。
响应式布局:viewport设置width=720, user-scalable=no ,不要设initial-scral,css媒体查询(media query)设置手机版样式。
问题
本人之前一直做手机专版和pc版分开,通过后端检查useragent跳转到对应页面。一次偶然的将手机专版的代码<meta name="viewport" content="width=device-width, initial-scale=1.0">
带到了一个纯pc站的页面。然后用手机访问,发现页面变得非常大,只能看到页面一角,必须手动缩小才能看到页面全貌。
结合在做手机专版页面时css样式宽度一直找不到合适的单位只能用百分比%,无法非常精准的贴合设计稿,希望能用习惯的px。于是想要好好弄清楚viewport到底该怎么设置,以解决一下问题:viewport该怎么设置,可以使PC端页面能缩放到合适大小,响应式页面能够用固定宽度设计,并且css用对应的px做单位。
探索:
viewport的基础知识可以在这篇文章看:《移动前端开发之viewport的深入理解》链接:https://www.cnblogs.com/2050/p/3877280.html。
这篇文章介绍了大神关于手机浏览器layout viewport,visual viewport,ideal viewport三个概念。
本文引用layout viewport,visual viewport两个概念并且在探索中发现了不一样的观点,也是本文的重点:visual viewport是个变化值,并且有个最大值,页面宽度大于visual viewport的最大值才会出现横向滚动条。
要研究为什么会出现滚动条,那除了上面layout viewport,visual viewport有关外,一开始设想应该和屏幕物理像素(screen width)还有浏览器虚拟的屏幕宽度(window width)有关。
当然,文档宽度(document width)也是关键点。实际探索发现和screen width没多大关系,但作为参考下面一起列出几个宽度的javascript获取放代码。
layout viewport -> document.documentElement.clientWidth
visual viewport -> window.innerWidth
window width -> window.screen.width
screen width -> window.screen.width * window.devicePixelRatio
下面探索开始(测试机型为:小米MI 6 X)。
准备:先从Photoshop截一张像素尺保存为:pxruler.png设置为body的背景作为参考。
以下是基本代码:
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="">
<style>
*{
margin: 0;
padding: 0;
}
body{
padding-top: 50px;
background: url(pxruler.png) no-repeat left top;
}
</style>
</head>
<body>
<div style="width:; height: 500px; color: #fff; background-color: #f00;">
<script>
document.writeln("<p>layout viewport(document.documentElement.clientWidth) : "+ document.documentElement.clientWidth+"</p>")
document.writeln("<p>visual viewport(window.innerWidth) : " + window.innerWidth + "</p>")
document.writeln("<p>window width:(window.screen.width) :" + window.screen.width + " </p>")
document.writeln("<p>screen width:(window.screen.width * window.devicePixelRatio) :" + window.screen.width * window.devicePixelRatio + " </p>")
</script>
</div>
</body>
</html>
一、滚动条什么情况下会出现?
第一步、不设置viewport,也不设置文档宽度。
测试结果:
layout viewport -> 980
visual viewport -> 980
window width ->393
screen width ->1080.75
没出现滚动条
可以看到layout viewport和visual viewport是相等的。
第二步、既然没滚动条那设置文档宽度比window width大看一下,设置为500。
测试结果:
与上面测试一至,
结论:滚动条和window width无关。
第三步、再设置文档宽度比layout viewport大,设置为1000。
测试结果:
layout viewport -> 980
visual viewport -> 1000
window width ->393
screen width ->1080.75
没出现滚动条,页面缩放了。
这次测试发现visual viewport变了,等于文档宽度(document width)。
第四步、滚动条没出现那再把文档宽度设大一些,设置为1800。
测试结果:
layout viewport -> 980
visual viewport -> 1572
window width ->393
screen width ->1080.75
出现滚动条,页面缩得更小了。
本次测试visual viewport变更大了但是比文档宽度小,并且出现了滚动条。
整理上面的测试,可以得出以下表:
结合上面测试可以得出结论:visual viewport是个变化值,并且有个最大值,页面宽度大于visual viewport的最大值才会出现横向滚动条。
实际上测试了更多文档宽度和机型,选取上面比较关键的几个宽度叙述。并且得知大部分手机默认layout viewport=980 , visual viewport(max)为1400到1600。
二、viewport的width改变的是什么?
设置好viewport的width=800后,同样进行前面的四步测试。
发现layout viewport固定为800;visual viewport也是最小为800,文档宽度大于800后visual viewport等于文档宽度;文档宽度大于visual viewport(max)后出现滚动条。
结论:viewport的width改变的是layout viewport及visual viewport的最小值。
三、viewport的width 大于visual viewport会怎么样?
viewport的width 大于visual viewport即使是空文档,也会出现滚动条。
小结:
通过前面的测试,我们知道了移动浏览器对页面的适应逻辑,即:比layout viewport小的页面能完整显示;比layout viewport大但是比visual viewport(max)小的那把页面缩放layout viewport大小完整显示;比visual viewport(max)还大的页面,按照visual viewport(max)缩放到layout viewport大小的比例缩放页面,超出部分需要滚动条。
四:device-width代表什么?
设置好width=device-width后测试发现layout viewport=visual viewport= window width。
结论:device-width代表浏览器虚拟的屏幕宽度,通常是比较小的值。即:《移动前端开发之viewport的深入理解》一文第五中图1的值。
五:initial-scale的影响。
我们已知initial-scale是指对文档的缩放。前面小结中已经知道了滚动条的逻辑,下面的测试就不测试文档宽度(document width)这个变量了。
第一步,先不设置viewport的width,设置一下initial-scale=1,进行测试。
测试结果
layout viewport ->393
visual viewport -> 393
window width ->393
screen width ->1080.75
测试发现layout viewport和visual viewport改变了和window width一样大。
第二步、设置viewport的width=800,initial-scale=1 进行测试。
测试结果
layout viewport ->800
visual viewport -> 800
window width ->393
screen width ->1080.75
出现滚动条,通过body设置的背景像素尺,可以发现实际显示宽度为393左右。
分析上面两步:可以得出结论,initial-scale=1,实际上将visual viewport限制为device-width(数值显示为layout viewport大小)了,第二步的滚动条符合,前面viewport的width 大于visual viewport必然出现滚动条的结论。
于是我们可以更准确的确定viewport的width主要还是设置layout viewport的作用,在出现initial-scale 的情况下,visual viewport主要由device-width决定。
第三步、设置viewport的width=800,initial-scale=0.5 进行测试
layout viewport ->800
visual viewport -> 800
window width ->393
screen width ->1080.75
出现滚动条,通过body设置的背景像素尺,可以发现实际显示宽度为750左右。实际上正好是786(393/0.5)。
经此三步测试,可以确定initial-scale是会改变visual viewport的实际大小的,改变为 visual viewport = window width/initial-scale。
再仔细分析,为什么会是这样的呢?
我们可以得出结论,initial-scale告诉了手机我要缩放的比例,比如说0.5,手机说好的,那我把visual viewport扩大到手机屏幕(device-width)的两倍,再把页面铺到visual viewport(页面大的话会有滚动条)里,然后又把带着页面的visual viewport缩放到手机大小,这不就缩放到0.5了么,完美!
等一下,好像漏掉点什么。对,还有viewport的width怎么办? 把layout viewport设置到width大小,按initial-scale缩放,在把铺好页面的visual viewport放进去。
总结:
不超过visual viewport(max)大小的页面,手机总能将页面缩放到layout viewport大小完整显示页面,超过visual viewport(max)的页面,按照visual viewport(max)缩放到layout viewport大小的比例缩放页面,超出部分需要滚动条。initial-scale会影响visual viewport的值。
所以结合需求,
pc专版页面:不需要设置viewport,因为手机会尽量按照合适大小缩放。
响应式页面:可以设置viewport的width为一个固定值(推荐为720),然后设计按照这个宽度做。当然先有设计稿,可以将固定值设为设计稿的宽度。不要设置为device-width,因为device-width各个设备不一致,也不要设initial-scale,避免visual viewport改变带来的影响。css样式通过媒体查询(media query)设置小屏幕页面大小为这个固定值。viewport可以这样设置:
<meta name="viewport" content="width=720 , user-scalable=no">
对于为什么width=720可以查看以下文章:《viewport的width值应该怎么设置》。