A tale of two viewports — part one

在以下的系列文章中,我将为大家解释浏览器中的视窗和一些重要的元素的尺寸是如何起作用的,如:大家最熟悉的html元素以及window和screen对象。

这篇文章作是本系列的第一部分,是关于台式电脑的浏览器的,主要目的是为后续的移动端浏览器的讨论奠定一个基础。大部分的web开发者能够凭直觉理解大部分台式机浏览器的概念。在移动端我们也将遇到一样的概念,不过对于这些人人都知道的概念进行更加复杂和预先的讨论将会极大地帮助大家理解移动端浏览器。

概念:设备像素和css像素

首先要理解的概念是理解css像素以及与设备像素之间的差异。

设备像素:设备像素是我们直觉上最容易理解的。这些像素是描述了所在设备的分辨率,可以通过screen.width/height来获取。假定给定一个元素的宽度为width:128px,显示器宽度是1024px,无缩放的情况下,要8个元素才能填满整个显示器。如果用户缩放到200%,只要4个元素就可以填满整个显示器。

现代浏览器中的缩放仅仅是拉伸像素。这意味着元素的宽度不会从128px变为256px,而是实际的像素尺寸变成双倍。元素的宽度仍然为128 css px,即使他占据了256个设备像素的空间。换句话说,缩放到200%使得一个css像素变成4倍的设备像素大小。

下面的图将解释这个概念。

(1)无缩放的4像素的图。css像素与设备像素完全重合 一个css像素等于一个设备像素

(2)缩小 css像素开始收缩,一个设备像素覆盖多个css像素

(3)放大 css像素开始变大,一个css像素覆盖多个设备像素

但是我们只关注渲染页面的css像素。设备像素对于前端工程师来说几乎没有什么用处。只有用户会缩放页面使得阅读舒适。浏览器会根据你的css样式去自适应页面元素的大小以及保持特定的元素比例。

屏幕尺寸

screen.width 和 screen.height分别表示用户屏幕的宽高。他们都是以设备像素衡量的,因为设备像素是不会改变的,设备像素是显示器的属性,与浏览器无关。

但是屏幕尺寸对我们来说没有什么作用,除非你想要建立一个web统计数据库。

window大小

我们感兴趣的是浏览器窗口的内部尺寸。这是用户当前css层可用的实际空间,分别是 window.innerWidth 和 window.innerHeight。

显然,窗口的内部宽度是用css像素衡量的。当用户放大的时候,你可以得到更少的窗口空间,window.innerWidth 和window.innerHeight将会变小。

(Opera浏览器是个例外, window.innerWidth/Height不会随着用户放大而缩小,他们以设备像素衡量。这在台式机中很烦人,在移动端中是致命的)需要注意的是,测量的widths 和 heights是包括滚动条的。

Scrolling offset

window.pageXOffset 和 window.pageYOffset 分别是document的横向和纵向的滚动距离。

这些也是以css像素衡量的。你可以知道文稿被滚动了多少,不论它是否被缩放。

理论上,如果用户页面向上滚动然后放大,window.pageX/YOffset会改变。然而,当用户缩放时,浏览器想要通过使得可见页面的顶部是同样的元素来保证网页的一致性。这通常并不能表现的很好,不过这使得实际的 window.pageX/YOffset 不会发生改变。

concept:viewport

viewport的作用是限制<html>元素,是最高级的块级容器。html的宽度是受view的宽度限制的,是viewport宽度的100%。

viewport正好等于浏览器窗口。

consequences

这样的限制机制会导致一系列的浏览器显示效果。如下,将屏幕滚动到顶部,然后放大2——3次使得网页的内容溢出浏览器窗口。然后滚动到最右侧,此时上面的的蓝色条块布局出现异常。

这就是viewport的定义导致的影响。蓝色条的width为100%。相对于什么元素的100%?相对于html元素的话,应该是与viewport等宽,也等于浏览器窗口宽度。关键的点是这在无缩放的情况下显示正常,此时放大的页面的使得viewport小于整个网页内容的宽度,网页内容溢出了html元素,但是这个元素是有益溢出的属性:overflow:visible,这表示溢出的内容不论怎样都会显示。但是蓝色条没有溢出。他的宽度为100%,浏览器会将它的宽度设为与viewport等宽。

document width?

ducument width表示网页内容的总宽度,但是没有这个css属性。

Measuring the viewport

viewport可以通过document.documentElement.clientWidth 和 -Height得到。

如果你了解dom,就会知道document.documentElement事实上是html元素,它是任何html文档的根元素。然而,viewport是更高一层的,它包括html元素。如果要给定html元素宽度,将会与viewport有关。在那种情况下,document.documentElement.clientWidth 和 -Height仍然是viewport的尺寸,而不是html元素。(这是viewport一个特殊的属性,其他的元素都是元素本身的属性)

因此,document.documentElement.clientWidth 和 -Height总是表示viewport的尺寸,与html元素无关。

Two property pairs

window.innerWidth/Height难道不表示vewport的尺寸么?是,也不是。document.documentElement.clientWidth 和 -Height不包括滚动条,而window.innerWidth/Height包括。这两个属性的出现源于浏览器大战。 Netscape仅仅支持 window.innerWidth/Height ,ie仅仅支持document.documentElement.clientWidth and -Height。从此,所有的其他浏览器都支持clientWidth/Height,但是ie没有选择window.innerWidth/Height。在台式机中,拥有这两种属性是不友好的,但是在移动端中应该庆幸。

Measuring the element

因此,clientWidth/Height在任何情况下都表示viewport的尺寸。html的尺寸则用 document.documentElement.offsetWidth 和-Height来表示。如果你设置html的尺寸,offsetwidth等会反应出来。



Event coordinates

1.pageX/Y 表示事件位置相对于html元素的css像素坐标位置。

2.clientX/Y 表示事件位置相对于viewport的css像素坐标位置。

3.screenX/Y 表示事件位置相对于screen的设备像素的坐标位置。

pageX/Y



lientX/Y



screenX/Y

Media queries

最后,是关于媒体查询,可以定义在不能页面尺寸下的css样式。

 div.sidebar {
width: 300px;
} @media all and (max-width: 400px) {
// styles assigned when width is smaller than 400px;
div.sidebar {
width: 100px;
} }

有两种相关的媒体查询: width/height 和 device-width/device-height。

1.width/height 与 documentElement .clientWidth/Height值相等(相对于viewport,css像素);

2.device-width/device-height 相对于screen,与screen.width/height的尺寸一致,是设备像素。

use width and forget device-width — on desktop

Conclusion

以上是关于台式机浏览器的一些属性和特征,关于移动端的见part2.

翻译原文地址:https://quirksmode.org/mobile/viewports.html

pc端和移动端的“窗口”(viewport)故事(part1)的更多相关文章

  1. 如何解决PC端和移动端自适应问题?

    做网页时,我们通常需要考虑到不同电脑屏幕尺寸,以及不同手机屏幕大小等问题,解决样式发生改变的情况,那么如何解决呢?现在主要是采用自适应来解决高度,宽度的,以及图片自适应问题,下面就PC端和移动端来总结 ...

  2. PC端、移动端的页面适配及兼容处理

    转自 一.关于移动端兼容性 目前针对跨终端的方案,主要分为两大阵营:一套资源Vs两套资源. 第一种是通过响应式或页面终端判断去实现一套资源适配所有终端: 第二种是通过终端判断分别调取两套资源以适配所有 ...

  3. 淘宝购物车页面 PC端和移动端实战

    最近花了半个月的时间,做了一个淘宝购物车页面的Demo.当然,为了能够更加深入的学习,不仅仅有PC端的固定宽度的布局,还实现了移动端在Media Query为768px以下(也就是实现了ipad,ip ...

  4. 在PC上测试移动端网站和模拟手机浏览器的5大方法

    在PC上测试移动端网站和模拟手机浏览器的5大方法 来源:互联网 作者:佚名 时间:03-19 10:14:54 [大 中 小]                最近公司要开发网站的移动版,让我准备准备知 ...

  5. JS pc端和移动端共同实现复制到剪贴板功能实现

    JS pc端和移动端实现复制到剪贴板功能实现 在网页上复制文本到剪切板,一般是使用JS+Flash结合的方法,网上有很多相关文章介绍.随着 HTML5 技术的发展,Flash 已经在很多场合不适用了, ...

  6. pc端适配移动端

    pc端和移动端共用一套代码 1. 允许网页宽度自动调整 在网页代码的头部,加入一行viewport元标签 <meta name="viewport" content=&quo ...

  7. 如何直接在 PC 端获取其它端设备的 UserAgent 信息呢?

    如何直接在 PC 端获取其它端设备的 UserAgent 信息呢 [博主]反骨仔 [原文地址]http://www.cnblogs.com/liqingwen/p/5909615.html 序 希望收 ...

  8. 区分PC端与移动端代码,涵盖C#、JS、JQuery、webconfig

    1)C#区分PC端或移动端 using System.Text.RegularExpressions string u = Request.ServerVariables["HTTP_USE ...

  9. 10天学会phpWeChat——第七天:创建一个自适应PC网站+H5移动端的模块

    本教程基于phpWeChat核心框架1.1.0+版本.下载地址:http://s.phpwechat.com/app_38026ed22fc1a91d92b5d2ef93540f20 通过前面六讲的系 ...

随机推荐

  1. Keras学习笔记一:修改数据读入方式为本地图片读入

    第一种方法: Keras官方给的图片去噪示例要自动下载mnist数据集并处理,不能修改和加入自己的数据集. from keras.datasets import mnist (x_train, _), ...

  2. git上传项目已经删除文件,但是Jenkins中没有删除

    jenkins 缓存造成的,需要清理工作空间

  3. 软工团队Git现场编程实战

    组员职责分工 成员 分工 鲍子涵 分配职责,整合代码 吴宜航 UI设计与实现 钟博 UI设计与实现(Main Coder) 黄海东 数据整理 王镇隆 前端api接口分析和使用(Main Coder) ...

  4. LeetCode 82. 删除排序链表中的重复元素 II(Remove Duplicates from Sorted List II)

    题目描述 给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中 没有重复出现 的数字. 示例 1: 输入: 1->2->3->3->4->4->5 输出: ...

  5. vue 指示点的疑点拓展

    1. 为什么 vue 组件中的 data 是一个函数 1. 为了保证组件的独立性和可复用性,data 是一个函数,组件实例的时候,这个函数将会被调用,返回一个对象,计算机会给这个对象分配一个内存地址, ...

  6. jmeter也能做Webservice接口测试

    百度到天气预报接口:http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl 新增RPC接口线程 调取的参数及调取天气结果的显示 ...

  7. 在oracle中使用基表建立月表的存储过程

    某些系统需要按月分表来保存数据.下面的存储过程演示了如何使用基表来建立每个月的月表. 处理思路是:     1:首先,为基表建立好表和对应的索引.     2:将基表保存到一个存储过程需要的表中.   ...

  8. __linux__、__POSIX__宏

    __linux__用于定义linux,__POSIX__不太了解,各系统的宏有如下: std::string getOsName() { #ifdef _WIN32 return "Wind ...

  9. ControlTemplate in WPF —— Calendar

    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" x ...

  10. [idea]创建一个控制台程序

    新建项目时,选择JBoss即可.