DOM系列:视窗、设备、滚动条和文档尺寸
在上一节中,学习了JavaScript如何获取和设置元素位置和尺寸相关的方法,另外在JavaScript的学习笔记当中也学习了视窗宽度、位置与滚动高度相关的JavaScript方法与属性。今天继续来学习DOM中相关的知识,这篇文章将学习视窗、设备、滚动条和文档等相关的尺寸。其实在前两篇文章中都有涉及这些知识,为了让DOM系列相关的知识更完善,所以再花点时间整理一些这方面的技术点,加强印象。
时至今日,构建Web应用程序是前端主要工作之一。这些Web应用程序要面对众多不同的设备终端,也就是说,我们需要让这些Web应用程序在各种屏幕、分辨率下都应该有一个较好的展示效果。
要将一个Web应用程序适配众多终端屏幕,需要知道的是有多少可用的空间。如果你接触过Web响应式设计(Web Responsive Design),就知道,Web浏览器客户端就可以很好的处理。最简单的方式就是使用CSS的媒体查询来处理,但也有很多同学通过JavaScript对最终的结果进行一些控制。不过,使用JavaScript来做的话,有许多计算的事情要做。当然,这些计算虽然是JavaScript来处理,但最终还是由浏览器本身来完成。
当涉及到使用JavaScript控制元素位置相关的交互内容时,不能仅依赖浏览器自动帮助我们做正确的事情。我们需要主动(人肉)地去做一些相关计算。听起来可怕,事实上并没有那么可怕,接下来的内容将告诉我们怎么通过JavaScript来做这些事情。当你阅读完这篇文章之后,你会惊叹的地说,原来就是这么的简单。
测量视窗的大小
不管是什么设备,都可以通过浏览器来查看Web页面。听起来很简单,对吧。从技术上讲,这并不完全准确。实际上,你可以通过浏览器的viewport
查看Web页面。
Viewport
Viewport指的是网页的显示区域,也就是不借助滚动条的情况下,用户可以看到的部分网页大小,中文译为“视窗”(或“视口”)。正常情况下,viewport
和浏览器的显示窗口是一样大小的。但是,在移动设备上,两者可能不是一样大小。
比如,手机浏览器的窗口宽度可能是640px
,这时viewport
宽度就是640px
,但是网页宽度有1200px
,正常情况下,浏览器会提供横向滚动条,让用户查看窗口容纳不下的560px
。另一种方法则是,将viewport
设成1200px
,也就是说,浏览器的显示宽度还是640px
,但是网页的显示区域达到1200px
,整个网页缩小了,在浏览器中可以看清楚全貌。这样一来,手机浏览器就可以看到网页在桌面浏览器上的显示效果。
简单点来说,视窗是指你的浏览器中实际用来显示网页的部分,比如像下图这样:
拿Chrome浏览器来举例,viewport
不包括浏览器的地址栏、状态栏或任何其他类型的用户界面。因为这些东西会占用空间。最后有一点很重要,viewport
也不包括滚动条占用的空间。
言外之意,根据浏览器开启的不同设置(比如浏览器窗口状态栏、地址栏等),你的视窗大小将有所不同:
正如前面提到的,viewport
是可缩放的。既然可以缩放,那就具有可缩放的相关规则。在Web页面中,可以在HTML文件的<head>
中像下面指定viewport
相关的规则:
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"/>
</head>
上面代码指定,viewport
的缩放规则是,缩放到当前设备的屏幕宽度(device-width
),初始缩放比例(initial-scale
)为1
倍,禁止用户缩放(user-scalable
)。
viewport
全部属性如下:
width
:viewport
的宽度height
:viewport
的高度initial-scale
:viewport
的初始缩放比例maximum-scale
:viewport
的最大缩放比例minimum-scale
:viewport
的最小缩放比例user-scalable
:viewport
的是否允许用户缩放
事实上,在JavaScript中,咱们测量viewport
的大小也很容易。调用document.documentElement
对象的clientWidth
和clientHeight
属性就可以测量出viewport
的width
和height
。
比如下面这个示例的代码,让你调整浏览器窗口大小时会更新viewportWidth
(视窗宽度)和viewportHeight
(视窗高度)两个变量的值:
let displayViewportSize = (e) => {
let viewportWidth = document.documentElement.clientWidth
let viewportHeight = document.documentElement.clientHeight
console.log(`viewportWidth: ${viewportWidth},viewportHeight: ${viewportHeight}`)
}
window.addEventListener('resize', displayViewportSize, false)
运行上面的代码,随着你改变浏览器窗口大小时,将会输出更改后视窗width
和height
的值,如下所示:
从《DOM树和遍历DOM》一节中,我们知道
document.documentElement
是HTML的根元素,即<html>
元素。clientWidth
和clientHeight
属性可以用来获取元素边框内区域的大小。也就是说,document.documentElement.clientWidth
和document.documentElement.clientHeight
分别获取的是html
元素边框内区域的大小。如果你未接触过这两个属性,建议你花点时间阅读一下《获取元素位置和尺寸》一文。
如前所述,viewport
的值不包括水平或垂直滚动条。但有时候,视窗大小的计算有可能也会包含滚动条的大小。如果计算的viewport
大小包括了滚动条大小的话,咱们可以使用window.innerWidth
和window.innerHeight
来进行计算。
注意,如果我们想测试整个浏览器的大小,那么可以使用
window.outerWidth
和window.outerHeight
两个属性。它们返回浏览器窗口整个大小,包括浏览器的标题栏、状态栏等等。
测量屏幕分辨率和尺寸
JavaScript中除了测量浏览器和视窗大小的属性之外,还有其他度量大小的属性。比如测量屏幕分辨率和尺寸的属性:
如果我们要测量屏幕的分辨率,可以使用下面这两对属性:
window.screen.width
和window.screen.height
指的是显示器屏幕的宽度和高度,包括工具栏、状态栏等;window.screen.availWidth
和window.screen.availHeight
指的是浏览器窗口在屏幕上可占用的空间(宽度和高度)
window.screen.width
和 window.screen.height
理论上返回的屏幕完整的分辨率:
这两个属性没有考虑到屏幕(比如任务栏)占用的空间,所以它们不能准确地知道要处理多少像素。如果要知道屏幕实际有多大尺寸,应该使用window.screen.availWidth
和 window.screen.availHeight
:
这两对属性在JavaScript中可以像下面这样使用:
let displayScreenResolution = () => {
let fullWidth = window.screen.width
let fullHeight = window.screen.height
let availableWidth = window.screen.availWidth
let availableHeight = window.screen.availHeight
console.log(`fullWidth: ${fullWidth}px; fullHeight: ${fullHeight}px; availableWidth: ${availableWidth}px; availableHeight: ${availableHeight}px`)
}
window.addEventListener('click', displayScreenResolution, false)
测量document的尺寸
接下来,咱们再来看看document
文档尺寸的大小。
可以通过document.body
的clientWidth
和clientHeight
属性来获取文档的大小。从前面学习的知识中,我们知道document.body
将获取的是<body>
元素。
如果我们想要获取文档document
的width
和height
,我们可以像这样写:
let displayDocumentSize = () => {
let docWidth = document.body.clientWidth
let docHeight = document.body.clientHeight
console.log(`Document's Width: ${docWidth}px; Document's Height: ${docHeight}px`)
}
docWidth
和docHeight
变量存储的是document
的width
和height
。如果你的document
(也就是body
元素)用的是百分比设置单位,你将看到你的文档的大小会根据视窗的大小变更。
比如,body
设置样式:
body {
width: 50%;
height: 50%;
}
运行displayDocumentSize()
函数之后,缩放浏览器,那么返回的docWidth
和docHeight
也会随之变化:
理论上,根文档元素是documentElement
,也就是对应的<html>
元素。而documentElement.clientWidth
和documentElement.clientHeight
分别获取的是浏览器可视区域的width
和height
。它包含了所有的内容,我们可以使用documentElement.scrollWidth
和documentElement.scrollHeight
来测量它完整尺寸。
这些属性对于常规元素很有效。但是对于整个页面来说,这些属性并不能正常工作。在Chrome、Safari和Opera浏览器中,如果没有滚动条,那么就使用documentElement.scrollHeight
,其获取的值甚至要比documentElement.clientHeight
小。但对于常规元素来说,这是无稽之谈。
那么要得到一个可靠的窗口大小,我们应该这样使用:
let scrollHeight = Math.max(
document.body.scrollHeight, document.documentElement.scrollHeight,
document.body.offsetHeight, document.documentElement.offsetHeight,
document.body.clientHeight, document.documentElement.clientHeight
);
滚动条尺寸
与滚动scroll
相关的方法主要有window
对象下的scrollX
、scrollY
、scrollTo
和scroll
;Element
对象下的scrollWidth
、scrollHeight
、scrollLeft
和scrollTop
。
有关于滚动条相关的API介绍,可以阅读JavaScript学习笔记系列中的《视口宽高、位置与滚动高度》一文。
有一点需要注意,大多数浏览器中可以使用documentElement.scrollLeft
和documentElement.scrollTop
来获取文档滚动条,但Chrome、Safari和Opera存有bug(比如157855、106133)。如此一来,我们应该使用document.body
来替代document.documentElement
。
幸运的是,在JavaScript中有两个特殊属性:
window.pageXOffset
:是scrollX
的别名,返回文档/页面水平方向滚动的像素值window.pageYOffset
:是scrollY
的别名,返回文档在垂直方向已滚动的像素值
注意,这两个属性是只读属性,不能修改。
除了上述提到的有关于滚动条的属性之外,还有window.scrollTo()
,window.scroll()
和window.scrollBy()
等属性。
window.scrollTo
方法用于将文档滚动到指定位置。它接受两个参数,表示滚动后位于窗口左上角的页面坐标。
window.scrollTo(x-coord, y-coord)
它也可以接受一个配置对象作为参数。
window.scrollTo(options)
配置对象options
有三个属性:
top
:滚动后页面左上角的垂直坐标,即y
坐标left
:滚动后页面左上角的水平坐标,即x
坐标behavior
:字符串,表示滚动的方式,有三个可能值(smooth
、instant
、auto
),默认值为auto
我们使用的时候可以像下面这样使用:
window.scrollTo({
top: 1000,
behavior: 'smooth'
});
window.scroll()
方法是window.scrollTo()
方法的别名。
window.scrollBy()
方法用于将网页滚动指定距离(单位像素)。它接受两个参数:水平向右滚动的像素,垂直向下滚动的像素。
window.scrollBy(0, window.innerHeight)
上面代码用于将网页向下滚动一屏。
如果不是要滚动整个文档,而是要滚动某个元素,可以使用下面三个属性和方法。
Element.scrollTop
Element.scrollLeft
Element.scrollIntoView()
其中scrollIntoView()
是HTML5新增的一个功能:元素滚动的API,功能是类似于锚点。
根据 MDN的描述,
Element.scrollIntoView()
方法让当前的元素滚动到浏览器窗口的可视区域内。
Element.scrollIntoView()
方法还有一个变体,即:Element.scrollIntoViewIfNeeded()
。该方法也是用来将不在浏览器窗口的可见区域内的元素滚动到浏览器窗口的可见区域。但如果该元素已经在浏览器窗口的可见区域内,则不会发生滚动。
有关于scrollIntoView
与 scrollIntoViewIfNeeded
的 API 介绍,这里不深入下去。如果感兴趣的话,可以阅读这篇文章。
总结
在《获取元素位置和尺寸》和《视口宽高、位置与滚动高度》两篇文章都有涉及JavaScript对视窗、滚动条、文档、元素大小尺寸相关的属性。由于自己是JavaScript的初学者,整理的相关学习笔记有点零乱。最后在这里简单的撸一下他们之间的关系。
属性名称 | 描述 | 备注 |
---|---|---|
offsetParent |
返回一个指向最近的(closest,指包含层级上的最近)包含该元素的定位元素 | 可以使用offsetParent获取最近的CSS位置(CSS-Positioned)的祖先 |
offsetLeft |
当前元素左上角相对于offsetParent 节点的左边界偏移的像素值 |
|
offsetTop |
当前元素相对于其 offsetParent 元素的顶部的距离 |
|
offsetWidth |
一个元素的布局宽度 | 测量包含元素的边框、水平线上的内边距、竖直方向滚动条以及CSS设置的宽度的值 |
offsetHeight |
元素的像素高度,高度包含该元素的垂直内边距和边框,且是一个整数 | |
clientTop/Left |
返回该方向的border 宽度 |
该属性不包含元素的padding 或margin |
clientWidth/Height |
获取元素边框内区域的大小 | 包括了内容的宽度和padding ,但不包含滚动条宽度 |
scroll |
滚动窗口至文档中的特定位置 | window.scrollTo 同样能高效地完成同样的任务 |
scrollLeft |
读取或设置元素滚动条到元素左边的距离 | |
scrollTop |
获取或设置一个元素的内容垂直滚动的像素数 | |
scrollWidth |
返回该元素区域宽度和自身宽度中较大的一个 | |
scrollHeight |
返回该元素内容高度 | 包括被overflow 隐藏掉的部分,包含padding ,但不包含margin |
scrollX |
返回文档/页面水平方向滚动的像素值 | pageXOffset 是scrollX 的别名 |
scrollY |
返回文档在垂直方向已滚动的像素值 | pageYOffset 是 scrollY 的别名 |
window.innerHeight |
浏览器窗口高度,如果存在水平滚动条,则包括滚动条 | |
window.outerHeight |
浏览器窗口整个高度,包括窗口标题、工具栏、状态栏等 | |
window.innerWidth |
浏览器窗口宽度,如果存在垂直滚动条,则包括滚动条 | |
window.outerWidth |
浏览器窗口整个宽度,包括侧边栏,窗口镶边和调正窗口大小的边框 |
扩展阅读
- DOM系列的获取元素位置和尺寸
- JavaScript学习笔记系列的视口宽高、位置与滚动高度
- CSSOM视图模式(CSSOM View Module)相关整理
window
对象scrollIntoView
与scrollIntoViewIfNeeded
API 介绍- Window sizes and scrolling
- Viewport, Device, and Document Size
如果文章中有不对之处,烦请路过的大婶拍正。如果这篇文章对您有所帮助,路过的大爷可以打个赏,让我有更大的动力去创作更多有用的教程。(^_^)
如需转载,烦请注明出处:https://www.fedev.cn/javascript/viewport-device-scroll-document-size.htmlNike Jordan Melo Shoes