5

viewport浅入

相信所有的 web 开发者都见过亦或用过这个神奇的 meta 标签头,亦或在不明白或者半明半蒙的情况下就用上了。

先来解个疑惑 ,上图

图片描述

chrome 的手持设备模拟器相信大家再熟悉不过了,那么左上角的320*480是神马 ?应该很多人已经在心里有了个答案。
在解开这个疑惑之前 需要引入一个概念:

A pixel is not a pixel is not a pixel

引用 W3cplus 此像素非彼像素中的一句话

图片描述

是的,想说明的就是这里的320*480指的是你的设备的 dpx 而非 CSS 中的 px

至于有什么区别呢?
当然有区别!:

设备的 px 是指度量设备大小尺寸的一种单位,而我们常在web 应用中使用的 px 是针对Web 应用开发用来度量应用程序中元素的相对尺寸,是一种抽象的概念和前面的设备像素是不搭噶的两种存在。

那么为什么当我们使用的 css 中的 px 来设计页面的时候 使用与设备上的的宽度一致时能够得到良好的视觉效应呢,且听我慢慢道来。


我们先看下

关于 viewport 的 相关声明语法

<meta name="viewport" content="name=value,name=value">

首先引用下 ppk 文章中的英文解释(网络上大部分的出处出自此):


Directives
Every name/value pair is a directive. (The word is my own invention.) 
There are six of them in total:

width     
    Sets the width of the layout viewport.
initial-scale       
    Sets the initial zoom of the page AND the width of the layout viewport.
minimum-scale
    Sets the minimum zoom level (i.e. how much the user can zoom out).
maximum-scale
    Sets the maximum zoom level (i.e. how much the user can zoom in).
height
    Is supposed to set the height of the layout viewport. It is not supported anywhere.
user-scalable
    When set to no prevents the user from zooming. This is an abomination that MUST NOT be used.

看不明白?好吧我找来翻译一把(翻译的有点强硬别见怪):

指令
每对键值对都是一个指令,(ppk 大神的叫法)以下总计共有6对:
width
    设置layout viewport的宽度(css px)
initial-scale 
    设置页面的初始缩放比例同时可以设置layout viewport的宽度
minimum-scale
    设置最小缩放比例(指用户能够缩小到多小)
maximum-scale
    设置最大缩放比例(指用户能够放大到多大)
height
    设置layout viewport的高度,但暂时不怎么被支持
user-scalable
    设置是否允许用户放大缩小。ppk 指出这个属性很邪恶,最好别用(偷笑)
    

看到这里或许又蒙了一半 layout viewport是什么鬼?

ppk 大神的意思是想象下在我们设置 viewport 后,浏览器能够生成3种 viewport 分别对应 visual viewportlayout viewportideal viewport

这里我不打算掺杂过多的这些理论,只想要简单明了的方式解释(忽悠)出 使用viewport 会发生什么事,如果对 ppk 大神的这些理论感兴趣可以 go here

1.A tale of two viewports — part one
2.A tale of two viewports — part two
3.Meta viewport


大概的了解到 viewport 的语法后接下来就是案例讲解

当不使用 viewport 时我们为 pc 设计的网站在手持设备上是怎么样的

这里拿百度的 pc 版做例子(因为 pc 版没有 viewport)首先在非模拟器状态下打开百度然后切换到模拟器状态下

图片描述

我们可以看到的是整个 pc 版的页面被压缩到宽度仅有320px(非 css 单位)的设备中 ,正常人都没办法使用吧?
那么,这个时候这个页面的宽度是多少呢(css px)?

图片描述

我们选中 html 元素,查看右下角的盒子样式 可以明确的看到当前的页面宽度是980px(css px)

也就是说浏览器在只有320dpx 的情况下展示了980px 的页面(明显可以看出这里的 dpx 与 px 并不是1:1的关系)

但是我们从左下角的样式表内并没有看到 html 的 width,那么这个 html 的980 px宽是哪来的呢

答案是来自 viewport的! 别忘记了上面的 viewport 语法,也就是说 viewport设置了宽度为980px,但是前面不是说了这个例子使用的是百度的 pc 端的页面没有 viewport 吗?

那由哪来的 viewport 设置宽度呢 ,看到这里相信已经有人有答案了,没错当你没有设置 viewport 的时候浏览器会自动为你采用默认值 那么默认值是多少?

这里找来 ppk 的测试
图片描述

什么意思呢 其实意思就是在默认的情况下(针对手持端)如果你没有设置过 viewport 那么我浏览器就会根据我自个设备决定采用viewport宽度是多少。

知道了这些还不够 ,那么为什么我有了 viewport 设置宽度之后 html 就会采用其宽度呢 :

可以这么理解,viewport是一种超越 html 元素的存在,当没有为 html 设置宽度的时候,html 的宽度继承于 viewport设置的宽度

就拿w3cplus举个例子:

图片描述

和上面的一样拿 pc 版测试,默认没有 viewport 查看 html 宽度果然为980px

接下来为 html 元素设置宽度为50% 可以看到效果 其宽度值为490px

图片描述

到这里我们可以得出一个总结:

viewport 其实就是设置在当前设备的宽度下展示多少CSS px的网页内容

上一个例子我们已经看到当 html 文档的宽度小于 viewport 的宽度是会有什么样的效果,那么反过来如果设置 html 的宽度大于 viewport 又会是什么效果呢

图片描述

这里设置 html的宽度为2000px 可以看出页面出现了滚动效果。

这里又得出一个总结:

当 html 文档的宽度小于 viewport 的宽度时以文档的实际宽度为准,文档少于 viewport 宽度的部分不显示内容,当 html文档的宽度大于 viewport 的时候,你能看到的区域依然是 viewport 的大小区域,不过你可以通过滑动或滚动页面来查看大于viewport 区域的内容

至此我们已经知道了设备宽度与 viewport 的宽度以及实际文档的宽度之间的关系。

通过上述的例子我们知道基本上 viewport 的默认宽度是980px,且浏览器会将者 viewport 大小的 html 文档塞进有限的设备宽度内(浏览器会动态计算文档的布局及内容),所以我们看到的东西都很小。
那么我们想要清除的看清文档内的内容怎么办 ,没错,缩小 viewport 的大小,什么原理?
当我们缩小 viewport 的宽度的时候文档的宽度也对应的被缩小,即一样的设备宽度,我显示的东西少了(这时候浏览器重新计算文档布局及内容)可以看到的结果是字体被放大了,内容都被放大了!

这里还是拿W3CPlus的网站做例子:一样的拿 pc 版的无 viewport 的文档放入手持设备内,没办法看清内容

图片描述

这时候我在控制台输入这么一段代码:

document.head.insertAdjacentHTML('afterbegin','<meta name="viewport" content="width=320">');

图片描述

这时候是不是清晰很多呢~。

知道了这个原理,那我们要把 viewport 的大小缩小到多小比较合适呢 ?答案是和你的设备宽度一样宽。但是并不是每个手持设备都是320dpx宽啊,这时候我们可以这样写 viewport 头:

<meta name="viewport" content="width=device-width">

这样就会自动计算你的设备宽度了,此处应该有掌声~

但是这个时候并未结束,是的 ,当你把你原先的980宽的页面重置成了320宽 那页面布局当然就发生变化了,惨的,无法入目,这时候就得考验大家的 css 功底了,如何避免不在此文章讨论范围内。


扩展思考

1.当我们在手持设备上放大缩小页面的时候,发生了什么?
2.设备的宽度与分辨率的关系?为什么我们在做 iphone 图的时候640但到了页面只能为320?

解释:
1.
当我们在手持设备上放大的时候,设备的大小不变(废话),viewport 的大小不变, html 的大小不变,那变的是什么?
我们知道当我们设置了 <meta name="viewport" content="width=device-width">页面的宽度是与设备的宽度一致的达到1:1的关系
其实变得是你的可视区域 也就是 ppk 大神说的visual viewport,抛开他的理论,简单的理解就是你当你触发放大的是个动作时,页面的每一 css px宽度对应了多个设备的像素宽度(这里暂时不谈分辨率),所以你能看到元素被放大了,但是由于设备的宽度有限,所以你看到的内容也就少了,而viewport在我们一旦设置好后没有手动修改的话是不会发生变化的包括这里。
故 缩小引发的原理一样。

2.
设备的宽度的 px 和分辨率的关系?
在没有视网膜屏幕出现前 除了些高清屏幕外,大部分的手持设备的宽度与分辨率像素是一对一的关系,直到视网膜屏幕的出现打破了这个格局 出现一个设备宽度对应2个或很多的分辨率像素,引发什么结果?当然是更清晰了,因为用了更多的像素去表达相同的一个设备宽度像素的内容。更多细节探讨可以自行 度娘 更多。

了解了设备宽度与分辨率的关系之后 解释下图片与分辨率的关系,通常图片的像素是与分辨率对应的,故设计师在 ps 上用640分辨率设计图片的时候起始也是对应我们的设备宽度320(前面解释到视网膜屏幕一个设备像素会对应2个到多个分辨率像素),设计出来的图片同理。当然你把设计出来的640分辨率像素的图片放在一样是320宽度像素下的视网膜设备和非视网膜设备下的效果看起来差不多其实仔细看还是有差别的即是否更高清的差别(可以拿安卓和 ios对比)。


弄清楚了viewport 这个小巨人后我们还得知道如何通过 js 代码来获取设备的宽度、viewport 的宽度以及 html 文档的宽度

总结如下(不包括 IE 及其他特殊情况):

/*
*1.获取包含滚动条尺寸的浏览器完整内部尺寸
*2.获取用户实际的看到的视口大小(即发送缩放后的可视区域大小|visual viewport 大小)默认等于viewport大小
*/
window.innerHeight
window.innerWidth 

/*
*1.设置的viewport大小
*/
document.documentElement.clientHeight
document.documentElement.clientWidth

/*
*1.HTML 文档大小
*/
document.documentElement.offsetHeight
document.documentElement.offsetWidth

/*
*1.设备大小
*/
screen.Height
screen.width

网上有大量的关于 viewport 的讨论,不乏各种大神的讲解,各有千秋。
以上只为个人多日查阅实践及总结,仅作参考!
多谢!


Tomson
2.3k 声望101 粉丝