深入理解viewport
这篇文章我已写成pdf,建议直接下载浏览。
链接:https://pan.baidu.com/s/1c4cwd7E 密码:jty1
《对viewport标签的理解》
——版权所有 @RYZZ
如转载或引用请加上该链接!
前言:(必读)
前端的小朋友们多多少少接触过这个标签,网上有很多关于这个标签的解释,但是无疑千篇一律,你不禁都会怀疑他们是不是相互抄袭的。
这篇文章是我自己对这个标签以及浏览器对网页渲染机制的一个理解(可能有误,但至少根据这样的理解能够说通该标签各种情况的原因)。
推荐使用Chrome开发者工具的移动端模拟器来测试该标签,这样编辑预览都很方便,当然我这篇文章的测试都是经过安卓(华为P10)和iOS(iPhone7)测试过的。
文章提出了一些自定义概念(双下划线表示),如果在学习中自己总结某个概念有助于你学习,是很好的习惯。
如果你对这篇文章有错误之处,恳请指正,但不要带上脏话,谢谢。
目录:
一、标签用法及其属性 ( P2 )
二、几个专业术语 ( P3 )
三、PC上vp机制和网页渲染原理 ( P4 )
四、移动端上vp机制和网页渲染原理 ( P6 )
标签一般用法:(不需要过多参数,我觉得用户还是需要自己的操作空间,当然如果你是想用HTML5开发混合应用,建议加上最大、小缩放和禁止用户缩放)
<meta name=”viewport” content=”width=device-width”>
属性:(属性各自作用不说了,百度一堆)
width:a value(px) | device-width
initial-scale 范围是(0.0, 10.0]
minimum-scale 同上
maximum-scale 同上
user-scalable “yes” | “no”
来认识几个与屏幕(包括手机屏幕,电脑屏幕,平板屏幕等等)有关的术语:
(1) 尺寸(单位:inch,即英寸):就是我们俗话说的你的手机是几寸的,它的大小是你手机对角线的长度。
(2) 分辨率(单位:px,即像素):指你手机的宽 × 高,比如iPhone7的分辨率就是750 × 1334px
(3) 像素密度(单位:dpi(dot per inch)或ppi(pixel per inch),安卓习惯用前者而苹果习惯用后者):对角线的像素个数除以对角线长,比如iPhone7的ppi = √(7502+13342) / 4.7 ≈327。
(4) 设备像素(单位:px):指的是组成屏幕的最小的单位,比如iPhone7水平就有750个设备像素,有时也称为像素点或点。
(5) 设备独立像素(单位:dp):简称dip(device independence pixel),是一种虚拟像素,CSS中的px单位就是一种设备独立像素,它能保证使用同一种设备独立像素单位的相同值在不同设备上显示的大小差不多。(如果我没讲清楚的话,这个你可以百度了解一下)
(6) 设备像素比(无单位,是个比值):简称dpr(device pixel ratio),指该设备上一个设备独立像素等于多少设备像素,比如CSS在iPhone7中,1px(这个px是设备独立像素的一种单位) = 2px(这个px是设备像素,就是iPhone7上的像素点)。使用window.devicePixelRatio属性来获取CSS的一个px(设备独立像素)在该设备上等于多少个px(设备像素),即设备像素比。
(7) viewport:简称vp,我们不做中文翻译,下面用图片来说明。(因为我觉得做了翻译反而会依据表面意思被误导,如果你有强迫症,我建议你翻译成“网页渲染图层”)
我们现在来了解一下PC上浏览器渲染网页的原理,这会有助于我们了解什么是vp以及移动端的布局原理。
看下图:(画的有点抽象,尽量去理解)
图中有个浏览器(有URL地址栏和三个黑色椭圆的那个大矩形就是),浏览器中淡蓝色部分就是我们浏览器显示网页的那个窗口(即window,html和window是重合的,但是body有8px的margin),而淡绿色的就是vp。这幅图显示的是网页过宽时候,我们拖动水平滚动条的滑块看页面时候的情况(淡蓝色底下有个黑色的实心矩形,就是滑块)。
如果你对window, html, body之间的默认布局不了解的话,建议先看下下图:
说明了:html(黑色线框)默认和window是重合的(去掉边框的话),body其实可以看做一个div元素,那么body也应该是独占一行(块级元素的霸气所在),所以红色线框的body也是独占一行的(注意body自带margin:8px,所以它与html有边距),然后再是绿色线框的div,同样独占一行。
对vp在PC浏览器上工作原理的归纳:
在PC上,vp默认和window(即浏览器窗口,它等价“浏览器可显示网页的区域”以及“浏览器可见区域”,这四个名词都是同个概念!)重合,也就是说vp的默认宽高就是window的宽高。
再来说个概念,网页内容最小宽:网页能够正常呈现的最小宽度
<style>
div{float:left}
.a{width:220px;height:100px;background:yellow}
.b{width:10%;height:100px;background:red}
</style>
<body>
<div class=”a”></div><div class=”b”</div>
</body>
如果浏览器窗口最大宽度为1000px(当前浏览器窗口的宽度,可以通过window.innerWidth获得),那么这个网页的最小宽就是220px + 1000px * 0.1 = 320px。
如果一个网页内容最小宽等于或小于body的width时,我们称这种布局为合理布局(如果body里面的元素最小宽之和不超过body,那么我们看网页就不需要水平移动了,直接从上往下浏览即可,浏览就很轻松很人性化,所以称之为合理布局),否则如果超过body的width(这时称为异常布局),这时vp的宽会*放大,直到刚好包裹住网页的内容的最小宽,然后再放入浏览器的window中,所以就会在底部出现水平滚动条。上面说了如果网页内容最小宽大于body时会有水平滚动条,那么如果网页内容的高(一般来说网页元素的高不会设置百分比)大于vp的高(vp的高默认就是当前window的高,前面说过),那么就会出现垂直滚动条。(body的高是不会像宽一样被撑破的)
也就是说,网页都是渲染到vp上去的,然后把vp放到浏览器窗口中给用户显示。
最后我们来说移动端的浏览器网页渲染原理:(以iPhone7为例)
在不加viewport标签时,此时iPhone7的vp宽默认980px,高默认1744px。(这个vp的宽比高就是iPhone7手机的分辨率宽比高值,都约等于0.56,有木有发现。但这点要和PC端的vp区别开,PC端的vp的高宽不受比例约束!)这时,会和PC端一样,在这个980px宽的vp的body(手机上body还是有8px的外边距)中加入网页内容,并且一般不超过body(即合理布局),网页在vp中渲染好之后,缩小这个vp使得vp的高和手机浏览器可见区域高一样时为止,所以你一般点开没有做移动端优化的网站都是一个被缩小过的网页。但是,如果这个网页是个异常布局呢?即网页内容最小宽超过了body,那么这个vp会*放大(没错和PC端一样)到刚好包裹住网页内容最小宽,这时vp就大于980px了,那么手机浏览器该如何缩放呢?还是一样,异常布局只是影响了vp的宽,没有影响vp的高,所以还是缩小到vp的高和手机浏览器窗口(这里用了窗口,即window,它也等价于浏览器可见区域,不要搞混了,同个东西,上面说过)的高一样为止了,这意味着这时手机浏览器底部会有一个水平滚动条,就是用来滑动来看超出的那些部分(即异常布局的超过body的部分)。
很抽象?看下图:
矩形A表示手机浏览器窗口,iPhone7的是375px
矩形B表示iPhone7的默认vp
矩形C表示一个异常布局网页,它的最小宽大于vp的宽,所以默认的vp宽会被放大至刚好包裹住网页的最小宽(红色箭头所示),但是vp的高不会被相应放大(就变成了红色线框的矩形大小)。这时,异常布局的网页在vp渲染好了,然后要放入窗口里了,它会被缩小,直到vp的高和窗口的高一样,这样就会出现一个问题,异常布局的网页超出body(即超出默认vp宽)的内容会显示在窗口外,所以浏览器地不会出现一个滚动条,来看这异常的部分。
唠唠叨叨那么多,那么加上viewport标签呢?这还简单了?
如果设置为width=device-width,意味着把默认vp按比例变成窗口宽的大小。(注意,vp的宽高都是被约束的,缩放宽时高也会被缩放,缩放高时宽也会被缩放,但是上面讲到的在异常布局中除外)这时,vp将与窗口重合。那么,如果是个合理布局的网页,那么显示出来的就是一个很标准的移动优化的网页,反之,如果是个异常布局,那么vp是不会再缩小的,因为vp的高已经和窗口高一样了,但是vp的宽却要包裹住异常布局的网页的最小宽,所以vp的宽会大于device-width指定的值(在iPhone7上为375px),所以会加上水平滚动条。同样,这个异常布局的网页的vp的宽高的缩放就不会被比例约束,因为它的宽是*缩放的。
如果设置的width大于device-width,比如设置个500px,那么vp的宽就是500px,高等比例放大为585 * (500/375) = 780px。(585px是width=375px时的vp高)这时的网页渲染原理不就和不加viewport一样嘛?合理布局就缩小vp使得vp高等于窗口高;异常布局会增大vp的宽,但是vp的高不会等比例增大(因为vp的宽是*增大的),然后在缩小vp使得vp高等于窗口高,并且出现水平滚动条。
如果设置的width小于device-width,比如设个200px,那么vp宽高就是200px × (200 / 375 * 585)px,然后再是看是否是合理布局,是的话等比例放大使得vp高等于窗口高,不是的话,就增加vp的宽,然后再等比例放大使得vp高等于窗口高,同样地,会出现水平滚动条。
2018年1月31日