响应式设计——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>



作者:csRyan
链接:https://www.jianshu.com/p/fb982ea8dce3
來源:简书

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值