响应式设计——layout viewport、visual viewport以及相关属性

在阅读这篇文章之前,你需要了解设备像素、逻辑像素(设备独立像素)和CSS像素的区别,见我的前一篇文章

layout viewport

layout viewport是网页布局的区域,它是<html>元素的父容器。只要你不在css中修改<html>元素的宽度,<html>元素的宽度就会撑满layout viewport的宽度。
很多时候浏览器窗口没有办法显示出layout viewport的全貌,但是它确实是已经被加载出来了,这个时候滚动条就出现了,你需要通过滚动条来浏览layout viewport其他的部分。
layout viewport用css像素来衡量尺寸,在缩放、调整浏览器窗口的时候不会改变缩放、调整浏览器窗口改变的只是visual viewport。

在桌面浏览器中,缩放为100%的时候,Layout Viewport宽度等于内容窗口的宽度。(你几乎不会在电脑上见过横向滚动条,除非你调整缩放)

但是在移动端,缩放为100%的时候,Layout Viewport不一定等于内容窗口的大小。当你用手机浏览浏览宽大的网页(这些网页没有采用响应式设计)的时候,你只能一次浏览网页的一个部分,然后通过手指滑动浏览其他部分。这就说明整个网页(Layout Viewport)已经加载出来了,只不过你要一部分一部分地看。

layout viewport

不要以为所有元素的位置都会在layout viewport的内部,你将body的一个子元素添加out类:

.out {
    position: absolute;
    right: -30px;
    background-color: red;
}

这个元素就会超出layout viewport 30px!

visual viewport

visual viewport就是显示在屏幕上的网页区域。通过前面的说明你应该已经知道visual viewport了:它往往只显示layout viewport的一部分。visual viewport就像一台摄像机,layout viewport就像一张纸,摄像机对准纸的哪个部分,你就能看见哪个部分。你可以改变摄像机的拍摄区域大小(调整浏览器窗口大小),也可以调整摄像机的距离(调整缩放比例),这些方法都可以改变visual viewport,但是layout viewport始终不变。
visual viewport用css像素来衡量尺寸,表示有多少个css像素能够被用户看到。

visual viewport

举个栗子:
为了让小小的手机屏幕也能够浏览宽大的网页(这些网页没有采用响应式设计),手机浏览器将layout viewport的默认宽度设为与电脑浏览器一样,比如980px,1024px(单位:CSS像素)。由于手机的屏幕逻辑像素宽度一般只有300~400逻辑像素,因此需要将多个css像素由1个逻辑像素显示(也就是缩小,千万不要忘记缩放比例=css像素边长/逻辑像素边长),让手机屏幕显示的css像素与网页的css像素一样多了,也就是visual viewport = layout viewport

用手机浏览电脑板网页

但是这会引发一个问题:字体小得难以阅读。为了方便阅读我们又不得不用手指将缩放调整到100%左右(一个设备独立像素显示一个css像素,对于我的手机来说,水平方向只有360个设备独立像素),这个时候visual viewport 只显示layout viewport的一部分了。


visual viewport只显示layout viewport的一部分

我们做前端开发一定要为移动端浏览器进行适配,也就是进行响应式设计。响应式设计的第一步就是在html中加入:

<meta name="viewport" content="width=device-width, initial-scale=1.0">

这个标签只对移动端浏览器生效,它将layout viewport的横向css像素数量设为屏幕的横向dips(定值),然后将初始缩放的值设为1.0,也就是让css像素的大小=dips的大小。这样,数值、单位都想等了,网页宽度也就等于屏幕宽度了,也不会出现横向滚动条。

dips是设备独立像素的缩写。设备独立像素也叫逻辑像素。

设置了viewport meta标签以后

可以看出,现在的字体大小合适了。网页的排版变化了,和电脑版的网页差别很明显。排版变化的原因是网站使用了媒体查询:在加载css的时候检测显示设备的属性,为不同的设备属性应用不同的样式。


相关属性

1. screen.width/height

上一篇文章说过的screen.width/height:整个屏幕的宽度和高度。这两个数值的单位是设备独立像素。这两个数值不随页面缩放、浏览器窗口大小而改变,在前端开发的过程中可以认为是固定不变的(除非你通过操作系统改变屏幕的分辨率)。这两个数值是操作系统决定的,由于设备独立像素比设备像素经常不等于1:1,实际屏幕物理像素的分辨率不一定是screen.width×screen.height。

iphone的实际分辨率和浏览器使用的分辨率

在上图中列出了iphone各个手机的设备分辨率IOS决定的分辨率(逻辑分辨率),我们只需要看这两行。

设备分辨率就是屏幕上的物理像素的数量,当手机厂商宣传自己的屏幕有多么清晰锐利的时候,相互攀比的就是这个数值。

逻辑分辨率就是screen.width/height。为什么iphone3GS以后的iphone都要把这个值设为实际屏幕分辨率的1/2或1/3呢?因为随着屏幕上塞进越来越多的真实像素,屏幕大小的变化却不那么明显,因此像素密度也越来越高。如果还让逻辑分辨率:真实屏幕分辨率=1:1,那么12px的字体就会越来越小,影响阅读体验。因此,后续的iphone用4个真实像素(甚至9个像素)组合成一个“逻辑像素”。这样,即使真实像素越来越小,每一个“逻辑像素”的大小变化不大。浏览器可以放心地使用逻辑像素来衡量大小,而不用担心真实大小在不同的显示器上出现严重偏差。

2. window.innerWidth/Height

visual viewport的大小,也就是浏览器内容窗口的大小,不包括菜单栏、地址栏、状态栏等,但是包括滚动条单位是CSS像素。通过这个属性你可以知道,当前的浏览器窗口可以容纳多少个css像素。当用户放大的时候这个数值会减少(因为css像素变大了),当用户缩小的时候这个数值增大。缩放改变浏览器窗口都会改变这个属性的值

Opera浏览器是例外,其单位是设备独立像素,也就是说如果你只调整缩放,这两个值不会改变。

与之对应的,window.outerWidth/outerHeight给出整个浏览器窗口的大小(包括各种栏),但是单位是设备独立像素

3. document.documentElement.clientWidth/Height

Layout Viewport的尺寸(Layout Viewport是<html>元素的父容器),单位是CSS像素

它与window.innerWidth/Height的唯一区别是,document.documentElement.clientWidth/Height不包含滚动条。

document.documentElement指的是html元素,通常Element.clientWidth应该给出元素的大小,但是document.documentElement.clientWidth/Height并不衡量html元素的大小,这是一个特例。

4. document.documentElement.offsetWidth/Height

<html>元素的尺寸,除非你在css中改变html的大小(很少有人这么做),否则html的宽度始终与Layout Viewport宽度相同。单位是CSS像素

5. window.pageX/YOffset

滚动距离,描述用户已经向右、向下滚动了多少个像素,也可以理解为visual viewport相对于layout viewport的偏移值。单位是CSS像素

当用户进行缩放的时候,浏览器会尽量保证:原先在内容区顶部的元素,在缩放以后依然在内容区顶部,看以下例子:

放大前

放大后

原本数字3在顶部,放大后3依然在顶部。window.pageYOffset大致相同。大致相同的原因是CSS像素数量不随着缩放而变化,原本在上方的内容高度有多少个CSS像素,放缩以后依然是多少个CSS像素。至于为什么不是完全相同,是因为"原先在内容区顶部的元素,在缩放以后依然在内容区顶部"这一机制无法完美地做到。


以下是测试用的代码,可以自己改动试试看(在电脑上使用chrome可以模拟不同的移动设备来调试,在开发者工具点击右上角的“toggle device toolbar”即可)


<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <!--<link rel="stylesheet" href="test.css" type="text/css" />-->
    <title>test viewport</title>
    <style>
        * {
            padding: 0;
            margin: 0;
            box-sizing: border-box;
        }
        
        .box {
            width: 100%;
            height: 200px;
            background-color: greenyellow;
        }
        
        .out {
            position: absolute;
            right: -30px;
            background-color: rosybrown;
        }
    </style>
</head>

<body>
    <div class="box">box</div>
    <div class="out">out</div>
</body>

</html>

谢谢阅读!后续我会更新更多有关响应式设计的内容!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容