admin管理员组

文章数量:1530085

目录

物理像素 & 物理分辨率

CSS像素 & 逻辑分辨率

设备独立像素 DIP & 设备像素比 DPR

屏幕尺寸 & 像素密度 PPI

视网膜显示屏 & 深入理解DPR、PPI的用途

位图和矢量图

位图分辨率  & 二倍图原理

视觉视口(visual viewport)

布局视口(layout viewport)

移动端浏览器的布局视口的默认宽度  

布局视口与初始化包含块

meta viewport

移动端浏览器对PC网页的默认缩放处理

理想视口与width:device-width

理想视口与initial-scale:1

理想视口 与 maximum-scale、minimum-scale、user-scalable


物理像素 & 物理分辨率

物理像素:即显示屏中植入的物理发光点。一个物理像素就是一个发光点。

物理分辨率:即我们常常说的分辨率概念,比如某某显示屏分辨率为1920x1080,这里的分辨率指的就是物理分辨率,含义是,显示屏在水平方向上有1920个物理发光点,在垂直方向上有1080个物理发光点。

CSS像素 & 逻辑分辨率

CSS像素:即CSS样式中的单位px,它是一种逻辑像素,可以指代一个或多个物理像素。

比如,大部分PC端显示屏的:1px = 1物理像素;而移动端显示屏的: 1px = 一个或多个物理像素

逻辑分辨率:即显示屏水平方向有多少px,垂直方向有多少px。

比如,大部分PC端显示屏,如果物理分辨率为1920x1080的话,则其逻辑分辨率为1920px * 1080px,因为在PC端显示屏中 1px = 1物理像素;

因此,PC端显示屏,我们可以将 物理分辨率 等价为 逻辑分辨率。而移动端显示屏却不一样。

由于移动端显示屏的 1px 可能指代更多的物理像素,因此移动端设备屏幕的  物理分辨率 ≠ 逻辑分辨率,如下是苹果手机的分辨率信息

iPhone 所有机型参数大全 (kylebing)

手机型号

逻辑分辨率

物理分辨率

iPhone 3GS320px * 480px320 × 480
iPhone 4320px * 480px640 × 960

可以发现:

  • iPhone 3GS显示屏的,1 px = 1 物理像素
  • iPhone 4显示屏的,1 px = 2 物理像素

分辨率层面:

  • iPhone 3GS屏幕中,1 逻辑分辨率 = 1 物理分辨率
  • iPhone 4屏幕中,1 逻辑分辨率 = 4 物理分辨率

如下图所示:

设备独立像素 DIP & 设备像素比 DPR

CSS像素其实本身无法直接对应到显示屏的物理像素点,因为显示屏设备千千万万,如果在CSS像素中内置所有显示屏设备的物理像素的换算逻辑,那么CSS像素将不堪重负。

因此在具有显示屏的设备中都会提供一个:设备独立像素,即Device Independent Pixels,简称DIP。

一般情况下,1 CSS像素 = 1 设备独立像素 = 1 DIP

而 1 DIP = 一到多个物理像素。

也就是说,将 CSS像素 与 物理像素的换算关系  转移为了 设备独立像素 与 物理像素的换算关系,然后 1 CSS 像素 只需要对应 1 设备独立像素即可。

这样做的好处是,CSS像素不需要保存与千千万万个不同设备屏幕物理像素的换算关系,这种换算关系直接保存在每个设备上。

我们将显示屏的   物理像素 : 设备独立像素  的比值称为  设备像素比,即Device Pixel Ratio,简称DPR。

例如

  • iPhone 3GS屏幕的DPR = 1
  • iPhone 4屏幕的DPR = 2

简单理解DPR,即 1px = ?物理像素,DPR是几,?就是几。

在浏览器中,我们可以通过 window.devicePixelRatio 获取设备屏幕的dpr。

屏幕尺寸 & 像素密度 PPI

无论是物理像素、还是CSS像素都是一种相对单位,它们无法用来描述一个屏幕的尺寸。

比如,别人问你屏幕尺寸是多少,你说1920x1080,别人听到后,可能脑海里就黑人问号了,然后你又说是 1920px * 1080px的,可能那个人头就大了。

在显示屏行业内,屏幕尺寸指的是:屏幕对角线的长度,单位使用英寸,1英寸 = 2.54厘米。

比如我们逛淘宝时,搜索显示器,在尺寸筛选栏中,看到的屏幕尺寸的英寸数,就是屏幕对角线的长度。

同时,我们还注意到,不同屏幕尺寸支持选择同一个物理分辨率,

比如,对于物理分辨率为1920x1080的显示器,我们既可以选择24英寸,也可以选择27英寸。

二者区别在于,物理像素密度

屏幕的物理像素密度,指的是每英寸长度中物理像素点的数量,即 Pixel Per Inch,简称PPI。

PPI计算公式如下:

function ppi(hp,vp,inch){
    return Math.sqrt(hp*hp + vp*vp) / inch
}

比如,我的PC显示器的屏幕尺寸是24英寸,物理分辨率是1920x1080,则PPI ≈ 92,即我的PC显示屏每英寸上大约有92个物理像素点

 

再比如,iPhone手机显示屏

手机型号

物理分辨率

屏幕尺寸(英寸)
iPhone 3GS320 × 4803.5
iPhone 4640 × 9603.5

 则

  • iPhone 3GS的PPI约为165,即每英寸上约有165个物理像素点
  • iPhone 4的PPI约为330,即每英寸上约有330个物理像素点

视网膜显示屏 & 深入理解DPR、PPI的用途

PPI越高,说明屏幕的每英寸上的物理像素点越多,那么这又有什么用呢?我们可以从下面这个视频的06:00开始看

2010年乔布斯发布iPhone4【中文字幕】_哔哩哔哩_bilibili

2010年,乔布斯在iPhone 4的发布会上,首次提出了Retina display 视网膜显示屏,即国内所说的高清屏,

相较于上一代的iPhone 3GS的Normal display 普通屏,视网膜显示屏有两点不同:

  • DPR 从1 变为了 2
  • PPI   从 165 变为了 330

但是,iPhone 4 的屏幕尺寸却和 iPhone 3GS的相同,都是3.5英寸。

屏幕尺寸不变的情况下,屏幕中植入了更多的物理像素点,这意味着每个物理像素点的所占据的区域变小了,如下图所示,每个方格就是一个物理像素点,可以发现,视网膜屏的1个物理像素点的宽高,仅为普通屏的一半。

因此iPhone 4显示屏中1个物理像素点所占区域,相当于iPhone 3G3显示屏中1个物理像素点所占区域面积的1/4

那么如果此时,继续使用 1 CSS像素 = 1物理像素 标准的话,相当于只是将屏幕中显示的内容缩小4倍后展示,意义不大。屏幕中的画面不仅不会变得更加清晰,反而会因为被缩小了而看不清楚。

因此,为了保持同一个内容,在iPhone 3GS的屏幕中,和iPhone 4的屏幕中具有一样的大小,出现了了DPR(1px = ? 物理像素)概念:

  • iPhone 3GS的DPR=1,即 1px = 1 物理像素,在1px * 1px区域内,只有1个物理像素点,即可占据屏幕 s 大小区域
  • iPhone 4的DPR = 2,即 1px = 2 物理像素,在1px * 1px区域内,有4个物理像素点,即可占据屏幕 4 * s/4,最终也是s大小

因此,DPR的作用是:屏幕尺寸不变时,扩大屏幕分辨率后,保证屏幕中显示的内容不会缩小。

iPhone 4 的 1px * 1px 区域中,由于包含的物理像素点更多,因此可以进行更加细腻的内容绘制,如下图所示:

 

总结一下就是:屏幕尺寸不变的前提下,DPR越大,则屏幕显示的内容越清晰。

而PPI,则是一种更加通用的,用来描述屏幕清晰度的概念。即PPI可以用来比较不同屏幕尺寸,不同物理分辨率的屏幕的清晰度。

比如,24英寸1920x1080的PC显示屏具有92ppi,而3.5英寸640x960的iPhone 4显示屏具有330ppi,很明显iPhone4 屏幕更加清晰。

乔布斯在iPhone 4发布会上还提出了论点,如果一个屏幕的PPI超过300,即每英寸(2.54cm)上有超过300个物理像素点(每个物理像素点长度约为85微米),则人眼就很难发现屏幕中植入的物理像素点。

大多数情况下,人们觉得屏幕不清晰是因为屏幕显示的内容出现了锯齿,而所谓的锯齿,即可以被人眼识别到的物理像素点。而物理像素点之所以能被人眼看到,就是因为物理像素点太大了,如果物理像素点足够小(屏幕尺寸不变下,即物理像素更多,更密),那么人眼就识别不到了,此时人眼就会觉得屏幕变清晰了。

而和PPI概念类似的还有一个DPI,所谓DPI,即dot per inch,即每英寸上的墨点数量,DPI常用于描述被打印机打印的内容的清晰度,而需要被打印机打印的内容的DPI不能低于300,否则打印出来的内容就出现锯齿。可能,乔老板参考了这点吧[doge]。

位图和矢量图

计算机中的图片有两种类型,分别是位图和矢量图。

常见的位图文件后缀名有:jpeg(jpg)、png、gif、bmp

常见的矢量图文件后缀名有:svg、ai

位图定义:

位图图像(bitmap),亦称为点阵图像或栅格图像,是由称作像素(图片元素)的单个点组成的。这些点可以进行不同的排列和染色以构成图样。当放大位图时,可以看见赖以构成整个图像的无数单个方块。扩大位图尺寸的效果是增大单个像素,从而使线条和形状显得参差不齐。然而,如果从稍远的位置观看它,位图图像的颜色和形状又显得是连续的。用数码相机拍摄的照片、扫描仪扫描的图片以及计算机截屏图等都属于位图。位图的特点是可以表现色彩的变化和颜色的细微过渡,产生逼真的效果,缺点是在保存时需要记录每一个像素的位置和颜色值,占用较大的存储空间。常用的位图处理软件有Photoshop(同时也包含矢量功能)、Painter和Windows系统自带的画图工具等。(来源:百度百科)

矢量图定义:

矢量图也称为面向对象的图像或绘图图像,在数学上定义为一系列由点连接的线。矢量文件中的图形元素称为对象。每个对象都是一个自成一体的实体,它具有颜色、形状、轮廓、大小和屏幕位置等属性。矢量图是根据几何特性来绘制图形,矢量可以是一个点或一条线,矢量图只能靠软件生成,文件占用内在空间较小,因为这种类型的图像文件包含独立的分离图像,可以自由无限制的重新组合。它的特点是放大后图像不会失真,和分辨率无关,适用于图形设计、文字设计和一些标志设计、版式设计等。(来源:百度百科)

位图和矢量图的最大区别就是:

  • 位图放大到一定程度后会失真
  • 矢量图无论放大多少倍都不会失真

关于图片失真:

图片失真即,图片变得模糊,位图之所以放大会变得模糊,是因为位图是由固定数目的图片像素点构成的,位图的放大其实是像素点的放大(特别注意:位图放大不是位图像素点数量的变多,而是指图像像素点数量不变的前提下,单个像素点的大小变大),一旦像素点变大,就会出现锯齿效果,人眼看到的模糊,其实就是看到了锯齿,也就是放大后的单个图片像素点。

矢量图之所以放大不失真,是因为矢量图不是由固定的图片像素点构成,而是由动态数量的图片像素点构成的,这里的动态数量是由矢量图的内部数学公式在图片放大过程中实时计算出来的。因此矢量图放大,其实是图片像素点的增加,而不是单个图片像素点的放大,因此矢量图放大不会出现锯齿,也就不会模糊。

因此,如果显示在屏幕上的图片是位图,则我们需要特别注意。

位图分辨率  & 二倍图原理

在windows系统中,位图的分辨率指的是:位图宽的像素数 x 位图高的像素数;

在PhotoShop制图中,位图的分辨率指的是:位图的PPI,即位图上每英寸有多少个像素

但是PS制图时,更加关心位图的宽、高像素,而不是分辨率,通常分辨率都是选择默认的72ppi。只有位图用于打印时,才需要特别设置分辨率。

这里为了不造成理解混乱,我们按照windows系统对于位图的定义标准,即:

位图的分辨率指的是:位图宽度(像素数) x 位图高度(像素数)

位图尺寸指的是位图对角线的长度,单位使用英寸,1英寸 = 2.54厘米。

在PS制图时,我们需要指定位图的宽、高像素数,以及位图的PPI,而不需要指定位图的尺寸

因为,我们完全可以通过PPI计算公式,反推出位图尺寸 

另外,不仅制图时,位图尺寸是次要的,在使用位图时位图尺寸也是次要的,

比如windows系统在位图属性栏中都不提供位图尺寸信息,我们只有将位图放入Word或PPT中,才能看到位图的尺寸

我们在网页开发中使用位图时,也不关心位图尺寸,而更关心位图的宽、高像素数。

需要特别注意的是,位图的宽、高的单位是“像素”,这里像素既不是指物理像素、也不是CSS像素,它只是用于定义位图宽、高的特殊单位。

位图本身是由一个个“像素格子”构成的,如下图我们在PS中将一个图片放大10倍后,就可以清晰地看见组成位图的“像素格子”

默认情况下,位图的单个像素格子 会投射到  屏幕的单个物理像素点上

因此:1 位图像素格子 = 1 屏幕物理像素点。

而在PC端,1 屏幕物理像素 = 1 CSS像素,

故可得:PC端显示屏上的 1 位图像素 = 1 CSS像素

因此,在PC端网页上显示位图时,位图分辨率就是其逻辑分辨率,比如位图分辨率为420 x 360,则默认情况下,其在网页的逻辑分辨率也为 420px * 360px。

但是,在网页上,我们可以任意地调整位图的width、height 样式属性值,但是位图逻辑分辨率的改变,并不会影响位图分辨率

比如,我们修改网页上位图的逻辑分辨率为 210px * 180px,但是实际上,位图分辨率依旧为 420 x 360。

因此,此时 1 CSS像素 = 2 位图像素。

也就是说,如果我们改变位图的逻辑分辨率,影响的只是 CSS像素 与 图片像素 的比例关系,而不会改变位图的宽、高像素数。 

接下来,我们通过一个例子看看移动端屏幕上位图显示特点:

analyze.png
analyze@2x.png

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <!-- <meta name="viewport" content="width=device-width, initial-scale=1.0" /> -->
    <title>Document</title>
    <style>
      * {
        margin: 0;
        padding: 0;
      }
    </style>
  </head>
  <body>
    <!-- analyze.png -->
    <img src="https://i-blog.csdnimg/blog_migrate/859859ef7cd29f0ba4289ef0dc5187aa.png" alt="" />
    <!-- analyze@2x.png -->
    <img src="https://i-blog.csdnimg/blog_migrate/dbf87c7ddca6400bdde205094aba6456.png" alt="" style="width: 420px; height: 360px" />
  </body>
</html>

如上网页中展示了两张位图,分别是analyze.png和analyze@2x.png,两张位图显示的图像是相同的,但是二者位图分辨率(即宽、高像素数)不同:

  • analyze.png: 420 x 360
  • anlyze@2x.png: 840 x 720

因此,默认情况下,这两张位图在网页中的默认逻辑分辨率为:

  • anlyze.png: 420px * 360px
  • anlyze@2x.png: 840px * 720px

但是,我们将anlyze@2x.png的逻辑分辨率缩小为420px * 360px,和anlyze.png保持一致。

则此时:

  • anlyze.png 的 1 CSS像素 = 1 图片像素;
  • anlyze@2x.png 的 1 CSS像素 = 2 图片像素

最终手机移动浏览器上两张位图显示效果如下:

我们发现:anlyze.png显示较为模糊,而anlyze@2x.png显示较为清晰。

这是为什么呢?

首先,anlyze.png和(重置逻辑分辨率后的)anlyze@2x.png对应的逻辑分辨率都是 420px * 360px,因此在移动端显示屏中,它们所需的物理分辨率取决DPR,比如本例是在iPhone 4中演示的,则DPR=2,因此anlyze.png和anlyze@2x.png的位图都需要对应 840 x 720 物理分辨率

然后,

  • anlyze.png 位图分辨率为 420 x 360,根据 1 位图像素 映射到 1 物理像素的图片显示原理,anlyze.png 理论上只能占据 420 x 360 个物理像素,为了让anlyze.png可以占据 840 x 720个物理像素,则此时只能将 位图单个像素格子放大,即让每个位图像素格子宽x2,高x2,注意只是单纯放大位图像素格子,而位图的分辨率(即宽、高像素的数量)不变。当位图像素格子放大后,每个像素格子可以占据4个物理像素点,因此anlyze.png共可以占据420 x 360 x 4 = 840 x 720 个物理像素点。但是由于位图的每个像素格子被放大了四倍,导致锯齿效果被放大,位图会变得模糊。
  • anlyze@2x.png 位图分辨率为 840 x 720,根据 1 位图像素 映射到 1 物理像素的位图显示原理,anlyze@2x.png可以占据840 x 720个物理像素点,刚好符合要求,不需要放大位图的像素格子。

所以,在移动端网页布局中,我们需要注意移动端设备的DPR,如果DPR=2,则我们在网页中插入位图时需要格外注意,比如我们网页中需要插入一个 420px * 360px 的位图,则实际上该位图的分辨率应该达到 840 x 720,才能保证位图在网页中清晰展示。

我们将这种分辨率宽、高像素 需要达到  实际CSS像素宽、高两倍的位图,称为二倍图。

如果,移动端设备的DPR=3,则相应的需要三倍图,原理和二倍图一致。

视觉视口(visual viewport)

前面我们已经了解很多关于 PC端屏幕 和 移动端屏幕 的相关知识,下面我们就要进入新的环节,即网页如何在屏幕上显示。

可能有的人很奇怪,网页不就是被浏览器渲染并显示到屏幕上嘛!

这种说法其实是不准确的,网页的显示其实是被限制显示在了浏览器的视觉视口内的。

所谓浏览器浏览器的视觉视口,即浏览器中用于展示网页的区域,该区域是除了浏览器页签区、地址栏区、菜单栏区、调试窗口区外的区域,如下红色框区域

 

浏览器的视觉视口大小受到显示器屏幕的尺寸的限制,即浏览器的视觉视口最大为显示器屏幕的大小。

视觉视口还有一个注意点,那就是“滚动条”是否为初视觉视口的组成部分,按照MDN的说法,视觉视口是不包含滚动条区域的。

VisualViewport - Web API 接口参考 | MDN (mozilla)

我们可以通过:

  • window.visualViewport.width 获取浏览器视觉视口的宽度(CSS像素)
  • window.visualViewport.height 获取浏览器视觉视口的高度(CSS像素)

布局视口(layout viewport)

网页的显示受到浏览器视觉视口大小的限制,但是网页的大小却不受视觉视口大小的限制。

举个例子,井底之蛙,井口就像是浏览器视觉视口,天空就像是网页,虽然井底之蛙只能看到井口大小的天空,但是天空实际远比井口大无数倍。

此时为了更好地描述完整网页和浏览器视觉视口之间的显示逻辑,产生了布局视口的概念。

我们可以将布局视口理解为,一个虚拟的框,它可以装下整个网页,浏览器视觉视口可以通过滚动条来移动布局视口,模拟效果如下:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      #win {
        box-sizing: border-box;
        width: 200px;
        height: 200px;
        border: 1px solid black;

        position: relative;
        margin: 200px 500px;
      }

      #win::after {
        content: "视觉视口";
        display: block;
        position: absolute;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -50%);
      }

      #viewport {
        position: absolute;
        left: 0;
        top: 0;
        box-sizing: border-box;
        width: 500px;
        height: 500px;
        border: 1px solid black;
      }

      #viewport::after {
        content: "布局视口";
        display: block;
        position: absolute;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -50%);
      }

      #scrollLR {
        position: absolute;
        left: 0;
        bottom: 0;
        box-sizing: border-box;
        width: 40px;
        height: 10px;
        background-color: black;
      }

      #scrollTB {
        position: absolute;
        right: 0;
        top: 0;
        box-sizing: border-box;
        width: 10px;
        height: 40px;
        background-color: black;
      }
    </style>
  </head>
  <body>
    <!-- win模拟浏览器窗口 -->
    <div id="win">
      <!-- viewport模拟视口 -->
      <div id="viewport"></div>
      <!-- scrollLR模拟浏览器窗口的水平滚动条 -->
      <div id="scrollLR"></div>
      <!-- scrollTB模拟浏览器窗口的垂直滚动条 -->
      <div id="scrollTB"></div>
    </div>

    <script>
      /* 水平滚动条 */
      scrollLR.addEventListener("mousedown", function (e) {
        let x = e.pageX - this.offsetLeft;
        let y = e.pageY - this.offsetTop;

        document.addEventListener("mousemove", move);

        function move(e) {
          let left = e.pageX - x;
          let leftMax =
            win.offsetWidth - scrollLR.offsetWidth - scrollTB.offsetWidth;
          let ratio = (viewport.offsetWidth - win.offsetWidth) / leftMax;

          if (left < 0) {
            left = 0;
          }

          if (left > leftMax) {
            left = leftMax;
          }

          scrollLR.style.left = left + "px";
          viewport.style.left = -left * ratio + "px";
        }

        document.addEventListener("mouseup", function () {
          document.removeEventListener("mousemove", move);
        });
      });

      /* 垂直滚动条 */
      scrollTB.addEventListener("mousedown", function (e) {
        let x = e.pageX - this.offsetLeft;
        let y = e.pageY - this.offsetTop;

        document.addEventListener("mousemove", move);

        function move(e) {
          let top = e.pageY - y;
          let topMax =
            win.offsetHeight - scrollTB.offsetHeight - scrollLR.offsetHeight;
          let ratio = (viewport.offsetHeight - win.offsetHeight) / topMax;

          if (top < 0) {
            top = 0;
          }

          if (top > topMax) {
            top = topMax;
          }

          scrollTB.style.top = top + "px";
          viewport.style.top = -top * ratio + "px";
        }

        document.addEventListener("mouseup", function () {
          document.removeEventListener("mousemove", move);
        });
      });
    </script>
  </body>
</html>

总结:

  • 浏览器的视觉视口大小受到显示器屏幕的尺寸的限制,即浏览器的视觉视口最大为显示器屏幕的大小。
  • 浏览器的布局视口大小不受视觉视口、屏幕尺寸的限制,默认情况下,PC端浏览器的布局视口大小就是网页文档的大小,但是移动端浏览器的布局视口却不一定

移动端浏览器的布局视口的默认宽度  

移动端浏览器的视觉视口:指的也是浏览器中用于显示网页的区域,如下图红框区域:

移动端浏览器的布局视口,默认情况下,并不等于网页本身大小,大部分移动端浏览器,如IOS的Safari,以及Android的众多浏览器的布局视口宽度width默认值都为980px。

为什么移动端浏览器会选择980px作为布局视口的默认宽度呢?

这其实要从iPhone 2G的发布说起,在2007年以前,99%的手机浏览器(Opera Mobile除外)基本上不支持访问PC WEB网页,主要原因如下:

手机浏览器本身是WAP浏览器,只支持访问WAP网页,不支持WEB网页。

WAP和WEB有什么区别? (soso)

2007年1月9日发布的iPhone 2G手机上搭载的Safari移动浏览器,让手机第一次真正拥有了一个可以访问PC WEB网页的内置浏览器(这里没说Safari是第一个移动WEB浏览器,貌似是因为Opera Mobile移动浏览器在2006年就已经实现在手机上访问PC WEB网页),下面是乔布斯对于它的介绍

乔布斯2007年iPhone发布会【4K高清】致敬经典!_哔哩哔哩_bilibilihttps://www.bilibili/video/BV1MN4y1771Q?spm_id_from=333.337.search-card.all.click&vd_source=b5105a99a0628dd906e154263279c518

我们可以在上面视频的41:24开始,看看iPhone 2G上Safari浏览器的运行演示。

iPhone 2G的Safari功能演示主要如下

  • 在移动浏览器Safari上访问PC WEB网页,初始加载时,网页被缩小到可以完整地在移动浏览器视觉视口中展示
  • 对网页进行双击放大,长按拖拽
  • 实现多页签打开网页
  • 支持竖屏横屏切换看网页

可能大家会觉得这些功能不应该是移动浏览器应该具备的最基本的功能吗?有什么值得演示的呢? 

当然,在2022年看来这些功能是基础的,但是在2007年看来,这些功能简直是划时代的。

回到正题,为什么大部分移动端浏览器都选择了980px作为布局视口的默认宽度呢?

那是因为iPhone 2G的Safari浏览器选择了980px作为布局视口的默认宽度。对,这就是榜样的力量。

那么为什么iPhone 2G的Safari选择980px作为布局视口的默认宽度呢?

因为那个时候,大部分PC网页的版心宽度都是980px。

那么什么是PC网页的版心?

网页的版心指的是:网页主体内容所在区域,该区域通常在网页内水平居中。如下图所示:

将网页主体内容放在网页版心位置,可以更加方便人眼阅读,提升阅读效率。

另外,版心的宽度一般都是固定的,而版心两侧的留白区域宽度是自适应的,这样有利于让网页适应不同宽度的PC屏幕。

比如,网页版心宽度设置为980px,则当

  • 屏幕宽度 > 980px时,则多出来的宽度平分到版心两侧留白区域
  • 屏幕宽度 = 980px时,则版心两侧留白区域消失
  • 屏幕宽度 < 980px时,则版心两留白区域消失,并且版心部分内容会被隐藏,我们需要通过视觉视口的滚动条来滚动查看

PC端网页版心的实现

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      /* 版心实现类 w  */
      .w {
        width: 980px;
        margin: 0 auto;
      }

      .head {
        height: 100px;
        margin-bottom: 10px;
        background-color: #eee;
      }

      .content {
        height: 500px;
        margin-bottom: 10px;

        background-color: #eee;
      }

      .foot {
        height: 200px;
        background-color: #eee;
      }
    </style>
  </head>
  <body>
    <div class="w">
      <div class="head"></div>
      <div class="content"></div>
      <div class="foot"></div>
    </div>
  </body>
</html>

而大部分手机显示屏的CSS像素宽度都是小于980px,比如iPhone手机的Plus或Max版本的CSS像素宽度最多不超过450px。

因此,绝大多数手机显示屏的宽度是放不下PC网页版心的,此时版心两侧留白宽度自适应为0,因此对于手机浏览器来说,此时PC网页版心宽度就是其网页宽度,因此我们将PC网页的版心最常用的宽度980px作为手机浏览器布局视口的默认宽度。

那么如果PC网页的版心宽度不是980px,而是1200px呢,那么此时移动浏览器的布局视口默认宽度会自动变为1200吗?

布局视口与初始化包含块

如果我们想要回答上一小节结尾的问题,则先了解如何测量浏览器布局视口的宽度?

布局和包含块 - CSS(层叠样式表) | MDN (mozilla)

在MDN的介绍中,布局视口的宽度 = 初始化包含块的宽度。而初始化包含块 指的就是 网页html根元素。

如下图中,在移动端浏览器中,html元素的宽度为980px,而移动端浏览器布局视口的默认宽度就是980px。

再比如下面例子

我们可以发现,虽然该网页的版心是1200px,但是移动端浏览器布局视口宽度还是默认的980px,即初始化包含块html元素的宽度。

meta viewport

iPhone手机上的移动浏览器Safari解析网页时,可以识别出文档head中的如下meta vieport标签

<meta name="viewport" content="" />

该meta标签的content属性具有如下描述属性

属性取值含义
width

[1, 10000] || “device-width”

默认值为980

用于设置移动浏览器布局视口的宽度

device-width表示100%的屏幕宽度

initial-scale

[0.1, 10]

默认值:1

控制页面首次加载时的缩放比例
minimum-scale

[0.1, 10]

默认值:0.1

控制页面缩小的最小比例
maximum-scale

[0.1, 10]

默认值:10

控制页面放大的最大比例
user-scalable

0 || no || 1 || yes

默认值:1 ,相当于yes

控制是否允许用户进行缩、放

我们需要注意的是,name="viewport"的meta仅用于移动端浏览器,对于PC浏览器无效。或者说,仅移动端浏览器支持meta viewport的解析,而PC浏览器不支持。

如果PC网页版心不是980px,此时PC网页就和移动浏览器布局视口默认的宽度980px不一致了,此时我们可以定义meta viewport的width属性来覆盖默认布局视口宽度,如下面例子

 此时,移动端浏览器就会将布局视口的宽度变为1200px,而不是默认的980px。

我们再来回头看看meta viewport的设置

<meta name="viewport" content="width=1200" />

虽然上面meta viewport只设置了width,但是实际上等价于

<meta name="viewport" content="width=1200, initial-scale:1, user-scalable:1, minimum-scale:0.1, maximum-scale:10 " />

因为,如果我们不设置这些属性,相当于取它们的默认值,而此时meta viewport的完整含义是:

  • width=1200:设置移动浏览器的布局视口宽度为1200px,即设置初始化包含看html根元素宽度为1200px
  • initial-scale:1:当网页首次加载时,网页缩放比例为1
  • user-scalable:1:允许用户对网页进行缩放
  • minimum-scale:0.1:对网页最小缩放比例为0.1
  • maximum-scale:10:对网页最大扩大比例为10

其中,width、user-scalable含义很简单,无需解释。

但是,initial-scale、minimum-scale、maximum-scale都是关于网页的缩放比例设置,那么这里网页为什么要缩放?这个缩放比例参照的又是谁呢?

移动端浏览器对PC网页的默认缩放处理

当乔布斯决定为iPhone 2G定制一款专属的移动端浏览器Safari时,它面临一个棘手的问题,那就是如何在手机这种小尺寸低分辨率的屏幕上,优雅地显示专门为PC端大尺寸、高分辨率屏幕设计的网页呢

比如iPhone 2G显示屏的:

  • 物理分辨率是320 x 480
  • 逻辑分辨率是320px * 480px
  • 屏幕尺寸是3.5英寸

但是当时市场上并没有专门为这么小的尺寸和这么低的分辨率的屏幕设计的网页,大部分网页都是按照PC端显示屏的分辨率设计,比如当时主流网页的版心宽度是980px。

乔布斯,首先敲定了移动浏览器Safari的布局视口的宽度为980px,来适应大部分的PC网页,此时移动浏览器显示PC网页的效果应该如下:(假设移动浏览器全屏显示)

即,移动浏览器只能展示部分的PC端网页,其余部分需要通过视觉视口滚动条滚动查看。

其实这种显示逻辑和PC端保持了一致,相当于我们将PC浏览器的视觉视口尺寸缩小到了手机屏幕尺寸的显示效果,如下图所示:

 我这里将PC浏览器的视觉视口宽度缩小到了320px,高度缩小到了480px,来模拟早期iPhone 2G的屏幕逻辑分辨率大小。

如果移动端浏览器采用和PC浏览器一样的显示逻辑的话,你会发现体验非常不好,每次都只能看到网页非常小的局部信息,可能PC网页的某个局部模块都需要多次拖动才能看全,这非常不符合人类的阅读习惯,反正就是很难受。

所以,乔布斯否定了网页首次加载时就以PC端网页原始大小展示的方案。

很快,乔布斯团队想到了一个新的方案,那就是网页首次加载时,直接将网页缩小到可以在移动浏览器的视觉视口中全部展示

但是此时网页内容被严重缩小了,很难看清楚,因此移动浏览器支持double touch网页,然后浏览器会自动将double touch的地方放大到适应屏幕。

 我们这里暂时不讨论double touch的放大局部的实现(其实原理也很简单),只讨论“PC网页初次加载时默认被缩小到,可以在移动浏览器的视觉视口中,全部展示”是如何做到的?

这里PC网页的缩放,其实就是移动浏览器布局视口的缩放

那么这里布局视口的缩放带来的影响是啥呢?

前面章节我们介绍图片的放大,图片放大并不会改变自身的图片分辨率(即宽、高像素数),只会改变图片像素 与 物理像素的比例关系,默认未放大的情况下,1 图片像素 = 1 物理像素,当图片放大四倍后(即宽放大两倍,高放大两倍),此时图片的宽、高像素数不变,只是每个图片像素格子可以占据四个物理像素点,即放大后单个图片像素格子的面积 是 放大前单个图片像素格子面积的四倍,图片像素格子的放大,会形成锯齿,造成图片显示的模糊。

同样地,布局视口的缩放,也不会影响布局视口的逻辑分辨率,比如缩放前,布局视口的宽度是980px,则缩放后,布局视口的宽度还是980px,变化的只是布局视口 1px 与 物理像素的比例关系。未缩放前,布局视口的1px = 1 物理像素(iPhone 2G),缩放后,1px 占据了 更少的物理像素,比如将980px布局视口缩放到320px宽度的显示屏范围内,则 1px 占据 320/980 ≈ 0.33 个物理像素,相当于1个物理像素发光点要显示原本3个物理发光点显示的色彩,这必然造成色彩合并,形成模糊效果。

也就是说,布局视口的缩放,不会改变自身的逻辑分辨率,只会让1px兑换更少的物理像素。

另外,布局视口的缩放,对视觉视口也有影响,原本视觉视口只有320px,也只能显示320px的内容,但是布局视口缩放到视觉视口中后,视觉视口需要展示980px的内容,因此视觉视口的逻辑宽度实际上增大为了980px,同样地,每1px 对应的物理像素也变少了,就1px = 0.33物理像素。

也就是说,布局视口的缩放会造成视觉视口的放大。

而meta viewport中 initial-scale: 1的含义,其实就是将布局视口缩放到视觉视口中。

那么initial-scale:2的话,移动浏览器会如何缩放PC网页呢?

视觉视口的宽度一般就是手机显示屏的宽度,比如iPhone 2G,视觉视口宽度就是屏幕宽度320px,initial-scale:1的话,表示将默认980px宽度的布局视口缩放到320px宽度内,即让布局视口的1px 只能换 320/980 ≈ 0.33个物理像素。

如果initial-scale:2的话,则表示将默认980px宽度的布局视口缩放到320px * 2宽度内,则此时布局视口将会超出显示屏。

当然,几乎没有网页设置meta viewport的initial-scale为2,这没有任何意义,我们只需要理解initial-scale:1即可。

理想视口与width:device-width

随着移动端的快速发展,越多越多的移动WEB网页开始出现,所谓移动WEB网页就是专门针对移动端屏幕尺寸和物理分辨率设计的网页。

比如 iPhone 2G的逻辑分辨率是 320px * 480px,则移动WEB网页也会将网页宽度限制在320px以内,但是此时出现一个问题,移动端浏览器的布局视口默认宽度是980px,即使你的网页宽度就是320px,但是移动浏览器也会将网页放到一个980px的布局视口中,然后将布局视口再次缩放到320px的屏幕中,最终效果如下:

这其实是事与愿违的。

因此我们需要通过meta viewport来覆盖默认的布局视口宽度

此时就OK了。

但是遗憾的是,一旦设置了 meta viewport width=320,则该网页在任何移动浏览器上的布局视口的宽度就总是320px了,这就对屏幕宽度不是320px的手机不友好,

因此我们希望可以设置meta viewport width的值为解析它的移动浏览器所在的设备的屏幕宽度,而正是考虑到这个需求,meta viewport width支持设置为 device-width,该值是一个特殊值,等于设备的屏幕宽度。

而当布局视口的宽度总是为移动端屏幕宽度时,我们称此时的布局视口就是理想视口。 

理想视口与initial-scale:1

除了设置meta viewport的width为device-width,可以将布局视口的宽度变为理想视口,我们还可以通过设置initial-scale:1让布局视口变为理想视口

 

那么如果此时我们设置meta viewport width的话,会影响initial-scale:1设置理想视口吗?

 答案是产生影响。

如果,width=device-width,则实际上,width、initial-scale设置的布局视口宽度都是理想视口宽度,最终布局视口宽度就是理想的。

 

如果,width>device-width,此时布局视口宽度以width为准,则最终布局视口宽度就不是理想的

 

如果,width<device-width,此时布局视口宽度以initial-scale:1为准,即理想视口宽度,则最终布局视口宽度是理想的

 

理想视口 与 maximum-scale、minimum-scale、user-scalable

当我们网页按照理想视口开发时,此时网页可以完美地在手机屏幕中展示,此时我们是不希望用户对网页进行放大、缩小操作的,如下是京东的移动WEB网页

因此,如果是按照理想视口开发的网页,我们需要禁止用户放大、缩小网页,此时meta viewport需要设置如下:

  • user-scalable:no   禁止用户放大、缩小网页
  • minimum-scale:1   网页最小缩放比例为1
  • maximum-scale:1  网页最大放大比例为1

此时完整的meta viewport设置如下

<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=1.0, maximum-scale=1.0, minimum-scale:1.0" />

即,在开启理想视口时,禁止用户缩小、放大网页。

需要注意的是,目前iPhone的Safari浏览器已经不支持maximum-scale,因此即使我们为移动WEB网页设置如上meta viewport maximum-scale,在Safari上还是可以放大网页。

而大部分国产浏览器都是支持maximum-scale的。

本文标签: 布局关键知识css