Window 大小和滚动

107 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第5天,点击查看活动详情

我们如何找到浏览器窗口(window)的宽度和高度呢?我们如何获得文档(document)的包括滚动部分在内的完整宽度和高度呢?我们如何使用 JavaScript 滚动页面?

对于此类信息,我们可以使用与 <html> 标签相对应的根文档元素 document.documentElement。但是还有其他方法和特性需要考虑。

窗口的 width/height

为了获取窗口(window)的宽度和高度,我们可以使用 document.documentElement 的 clientWidth/clientHeight

例如,这个按钮会显示窗口的高度:

alert(document.documentElement.clientHeight)

不是 window.innerWidth/innerHeight

浏览器也支持像 window.innerWidth/innerHeight 这样的属性。它们看起来像我们想要的,那为什么不使用它们呢?

如果这里存在一个滚动条,并且滚动条占用了一些空间,那么 clientWidth/clientHeight 会提供没有滚动条(减去它)的 width/height。换句话说,它们返回的是可用于内容的文档的可见部分的 width/height。

window.innerWidth/innerHeight 包括了滚动条。

如果这里有一个滚动条,它占用了一些空间,那么这两行代码会显示不同的值:

alert( window.innerWidth ); // 整个窗口的宽度
alert( document.documentElement.clientWidth ); // 减去滚动条宽度后的窗口宽度

在大多数情况下,我们需要 可用 的窗口宽度以绘制或放置某些东西。也就是说,在滚动条内(如果有)。所以,我们应该使用 documentElement.clientHeight/clientWidth

DOCTYPE 很重要

请注意:当 HTML 中没有 <!DOCTYPE HTML> 时,顶层级(top-level)几何属性的工作方式可能就会有所不同。可能会出现一些稀奇古怪的情况。

在现代 HTML 中,我们始终都应该写 DOCTYPE

文档的 width/height

从理论上讲,由于根文档元素是 document.documentElement,并且它包围了所有内容,因此我们可以通过使用 documentElement.scrollWidth/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
);

alert('Full document height, with scrolled out part: ' + scrollHeight);

为什么这样?最好不要问。这些不一致来源于远古时代,而不是“聪明”的逻辑。

获得当前滚动

DOM 元素的当前滚动状态在其 scrollLeft/scrollTop 属性中。

对于文档滚动,在大多数浏览器中,我们可以使用 document.documentElement.scrollLeft/scrollTop,但在较旧的基于 WebKit 的浏览器中则不行,例如在 Safari(bug 5991)中,我们应该使用 document.body 而不是 document.documentElement

幸运的是,我们根本不必记住这些特性,因为我们可以从 window.pageXOffset/pageYOffset 中获取页面当前滚动信息:

alert('当前已从顶部滚动:' + window.pageYOffset);
alert('当前已从左侧滚动:' + window.pageXOffset);

这些属性是只读的。

我们也可以从 window 的 scrollX 和 scrollY 属性中获取滚动信息

由于历史原因,存在了这两种属性,但它们是一样的:

  • window.pageXOffset 是 window.scrollX 的别名。
  • window.pageYOffset 是 window.scrollY 的别名。