10081677wc / blog

78 stars 6 forks source link

viewport 那些事儿 #13

Open 10081677wc opened 6 years ago

10081677wc commented 6 years ago

viewport 那些事儿

移动端的三个视口(update)

视口是 html 的父元素,所以我们称视口为初始包含块,html 元素的百分比是基于视口的。

布局视口

在 PC 浏览器中视口只有一个并有 视口的宽度 = 浏览器窗口的宽度 ,而如果在移动端根据同样的设计方案进行开发,网站会看起来很丑(因为手机屏幕要比 PC 显示器窄的多),布局视口就是浏览器厂商为满足用户的要求而提出的解决方案(即在手机上也能浏览为 PC 端设计的网站)。

在移动端视口和浏览器窗口将不再关联,实际上布局视口要比浏览器窗口大的多,在手机和平板中浏览器布局视口的宽度通常在 768~1024 像素之间,我们可以通过以下代码获取布局视口的宽度和高度:

document.documentElement.clientWidth
document.documentElement.clientHeight

样式布局是根据布局视口来计算的。

视觉视口

视觉视口即是用户通过手机屏幕看到的区域。

理想视口

布局视口并不是理想的宽度,所以我们需要理想的布局视口来满足我们的需求(移动端更适合的网站),比如对于 iPhone5 来讲其理想视口是 320*568,以下代码可以告诉手机浏览器把布局视口理想化:

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

上面代码中的 width 指的是布局视口的宽,而 device-width 实际上就是理想视口的宽度,我们使用 meta 标签的主要目的就是设置布局视口的尺寸,让布局视口和理想视口匹配。


在响应式 mobile-web 开发中,经常可以看到下面这行代码:

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

举例如 iphone6 手机,屏幕分辨率为 1334×750,浏览器分辨率为 667×375,它们的单位都是像素,但是很明显在 mobile-web 开发中,我们只考虑浏览器分辨率,而不考虑屏幕分辨率。我们把浏览器的可视区域称为 visual-viewport,但是某些网站会因为可视区域过窄而产生各种各样的显示错乱,所以浏览器会在默认情况下把 viewport 设为一个较大的值,这样的话那些没有考虑响应式设计的网页也可以在手机端正常显示了(像在 PC 端显示得一样),我们把这个虚拟的窗口称为 layout-viewport,下文中省略为 viewport。

可以把 layout-viewport 想像成为一张不会变更大小或者形状的大图,然后想像你有一个较小的框架,并通过它来看这张大图(管中窥豹),这个小框架的周围被不透明的材料所环绕,掩盖了你所有的视线,只留这张大图的一部分给你,其中你通过这个框架所能看到的大图的部分就是 visual-viewport。当你远离框架时(缩小),你可以看到大图更多的部分;或者你也可以靠近一些(放大)只看局部;并且你也可以移动框架的位置以看到大图的其他部分。但是无论你怎样操作这个小框架,大图(layout-viewport)的大小和形状永远不会改变。

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <!-- <meta name="viewport" content="width=375"/> -->    
    <title></title>
</head>
<style>
    body {
        padding: 100px 0px 0px 0px;
        margin: 0px;
    }

    div {
        width: 375px;
        height: 100px;
        /* 宽度与浏览器宽度一样 */
        color: white;
        font-family: "Microsoft Yahei";
        font-size: 1.5em;
        background-color: black;
        text-align: center;
        /* div块内字体水平居中 */
        line-height: 100px;
        /* div块内字体垂直居中 */
        margin: 0px auto;
        /* div块居中 */
    }
</style>
<body>
<div>
    <strong>Hello World</strong>
</div>
</body>
</html>

上述代码中设置 div 块宽度为 375px,与浏览器的宽度一样,但是没有声明 viewport 属性,结果并不如预期的一样(文字块占满浏览器的全部宽度),而是如下图所示:

图片描述

所以在手机端想要展示如我们预期的网页,必须设置 viewport 属性:

  • width(viewport 的宽度):200~10000的整数 | “device-width”
  • height(viewport 的宽度):223~10000的整数 | “device-height”
  • initial-scale(初始的缩放比例):大于0小于10的浮点数
  • minimum-scale(允许用户缩放到的最小比例):大于0小于10的浮点数
  • maximum-scale(允许用户缩放到的最大比例):大于0小于10的浮点数
  • user-scalable(用户是否可以手动缩放):“yes” | “no”

并且对于这些属性,我们可以设置其中一个或者多个,而不需要同时设置,手机会根据已设置的属性自动推算其他属性值,而非直接采用默认值。

图片描述

设置 viewport 属性 initial-scale=1.0 可以得到预期的效果,如上图所示。设置 initial-scale=1.0 说明此时单位物理像素(device-pixel)等于显示像素(css-pixel),手机不会自动缩放(即 viewport 的宽度为 375px,与文字块宽度相同,被其占满)。说到物理像素和显示像素,二者很容易混乱,其中最直观的一点区别是:单位物理像素是不变的(其值通常可以通过 screen.width/height 获取),而单位显示像素是相对的、可变的。在样式设计中我们给元素设置的宽度 width:128px,其单位是显示像素,在宽度为 1024px 的显示器上会重复八次,浏览器在实现缩放时都是在“拉伸”像素,举例如用户将网页放大到 200% 时,宽度为 128px 的元素的 width 数值没有改变,但是在宽度为 1024px 的显示器上只会重复四次,即是此时此刻单位显示像素等于四单位物理像素,二者改变了映射关系。

设置 viewport 属性 width=375 或者 width=device-width 同样可以得到预期的效果(注意此处的 device-width 与屏幕分辨率的宽度不相等,与媒体查询中的 device-width 是不同的值)。

并且手机浏览器在展示网页时,若手机屏幕的尺寸小于 viewport(默认为 980px),则用户看到的页面是 viewport 按照手机屏幕的尺寸等比例缩放而来的(即自动适应 initial-scale 为小于 1.0 的浮点数);若手机屏幕的尺寸大于 viewport,则浏览器会自动扩展(expand),而不是缩放(zoom)。