📓The Modern JavaScript Tutorial: Window sizes and scrolling JavaScript 译文

张宝 发布于 4个月前

在 DOM 中,document.documentElement 对应的是 <html> 元素。

窗口的宽/高

document.documentElementclientWidth/clientHeight 表示窗口的宽/高。

⚠️为什么不用 Window.innerWidth/Height

因为 Window.innerWidth/Height 的宽/高是包含滚动条的(有的话),而 document.documentElementclientWidth/clientHeight 是不包含的。

大多数情况下,我们操作的都是实际内容区的宽高,这里不应该包含滚动条。所以不用 Window.innerWidth/Height

alert( window.innerWidth ); // full window width
alert( document.documentElement.clientWidth ); // full window width 减去 scrollbar 的

文档的宽/高

这也指页面的宽/高。document.documentElement 就是 <html>,所以它的 scrollWidth/scrollHeight 属性就能表示文档的宽/高。但这里有个问题。

Chrome/Safari/Opera 中,如果页面没有包含滚动条,documentElement.scrollHeight 可能比 documentElement.clientHeight 还要小!当然,在页面包含滚动条的情况下,使用 documentElement.scrollHeight 是没有问题的。

下面给出计算文档高的最佳实践代码:

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);

当前滚动条滚动距离

普通元素有 elem.scrollLeft/scrollTop 接口来计算元素的滚动距离。那么页面呢?

许多浏览器提供了 documentElement.scrollLeft/Top 接口计算当前页面的滚动条滚动距离。但在 Chrome/Safari/Opera 中有 Bug,需要使用 document.body 来获得当前滚动条滚动距离。当然,这是特性怪癖,我们不用担心这个。

因为我们有 window.pageXOffset/pageYOffset 接口可以使用。

alert('Current scroll from the top: ' + window.pageYOffset);
alert('Current scroll from the left: ' + window.pageXOffset);

window.pageXOffset/pageYOffset 属性是只读的。

滚动方法:scrollTo、scrollBy、scrollIntoView

普通元素可以通过设置 scrollTop/scrollLeft 属性来滚动指定距离。

对于页面滚动:

  1. 对于 Chrome/Safari/Opera:使用 document.body.scrollTop/Left
  2. 对于其他浏览器:使用 document.documentElement.scrollTop/Left

有浏览器兼容问题,不好对付,可别担心。

因为我们有 window.scrollBy(x,y)window.scrollTo(pageX,pageY) 方法可以用。

  • scrollBy(x,y) 针对当前位置进行滚动。
  • scrollTo(pageX,pageY) 方法相对文档的左上角滚动,效果等同于设置 scrollTop/Left

而且 window.scrollBy(x,y)window.scrollTo(pageX,pageY) 方法兼容所有浏览器。

scrollIntoView

为了完整性,我们才讲 elem.scrollIntoView(top) 方法。

这里的参数 top 是个布尔值:

  1. top 值为 true 时(默认),滚动的最终效果是:元素顶端与窗口顶端对齐。
  2. top 值为 false 时),滚动的最终效果是:元素底端与窗口底端对齐。

禁止滚动

有时页面弹出弹框时,为了与弹框更好的交互,我们希望弹框层下面的长长的页面禁止滚动。

这时,可以设置 document.body.style.overflow = "hidden" 来实现这个效果----滚动条消失,页面固定在当前滚动的距离。

不仅 document.body,我们也可以在普通元素上使用这个方式,实现禁止滚动的效果。

🤔有一个问题。

是这样的,当使用 document.body.style.overflow = "hidden" 后,页面滚动条消失了。因为滚动条消失,之前占据的页面空间就没有了,所以页面内容可能就会往外拓展了。

为了保证页面内容不动,我们可以给 document.body 添加一个 padding 来替代之前滚动条占据的空间。

总结

几何属性:

  • 窗口宽/高(即文档可视区的宽/高,也是不包含滚动条的内容区域):document.documentElement.clientWidth/Height
  • 文档宽/高(即页面宽高):
let scrollHeight = Math.max(
  document.body.scrollHeight, document.documentElement.scrollHeight,
  document.body.offsetHeight, document.documentElement.offsetHeight,
  document.body.clientHeight, document.documentElement.clientHeight
);

滚动距离:

  • 当前滚动条滚动距离:window.pageYOffset/pageXOffset
  • 改变滚动距离:
    • window.scrollTo(pageX,pageY):绝对坐标(文档左上角)滚动。
    • window.scrollBy(x,y):相对(当前位置)位置滚动。
    • elem.scrollIntoView(top): 让元素 elem 元素滚动到可视区(与窗口顶端或者底端对齐)。

(完)


登录参与评论