九、window 大小和滚动控制

9.1 窗口的 width/height

我们要如何获取整个浏览器的宽高呢?我们可以使用html标签对应的document.documentElement中clientWidth和clientHeight

window.innerWidth/Height也能够获取,它们的区别是clientWidth/Height是一定不包含滚动条的。

我们一般需要的是可用的内容空间以放置元素,而inner*属性有可能会返回包含滚动条的空间,所以我们应该使用client*属性更加准确一些。

9.2 文档的完整宽高

从理论上来说,我们可以通过documentElement.scrollWidth/Height来获取文档的完整宽高。

但由于历史原因,我们必须采用以下方式来可靠地获取文档的完整宽高。

javascript
1let scrollHeight = Math.max(
2  document.body.scrollHeight,
3  document.documentElement.scrollHeight,
4  document.body.offsetHeight,
5  document.documentElement.offsetHeight,
6  document.body.clientHeight,
7  document.documentElement.clientHeight,
8)
9let scrollWidth = Math.max(
10  document.body.scrollWidth,
11  document.documentElement.scrollWidth,
12  document.body.offsetWidth,
13  document.documentElement.offsetWidth,
14  document.body.clientWidth,
15  document.documentElement.clientWidth,
16)

9.3 文档当前滚动状态

我们能够通过scrollTop和scrollLeft来得知 DOM 元素当前的滚动状态。

文档滚动我们大多数情况也可以通过document.documentElement.scrollTop/Left来获取。

但由于浏览器的兼容性原因,我们最好使用以下属性获取当前文档的滚动状态。

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

不过这个属性是只读的。

9.4 控制滚动

  • 元素滚动:设置 scrollTop/scrollLeft

  • 文档滚动:设置document.documentElement.scrollTop/Left,Safari 浏览器需要用document.body.scrollTop/Left,不建议用

  • 通用滚动(根据当前位置的(x,y)坐标偏移):window.scrollBy(x,y)。例如,scrollBy(0,10) 会将页面向下滚动 10px。

  • 通用滚动(根据页面的绝对坐标(x,y)):window.scrollTo(pageX,pageY)。例如,scrollTo(0,0)会让文档滚动到最顶上。

  • 通用滚动(滚动到某个元素上):elem.scrollIntoView(top)

    当top=true时,页面滚动,使elem出现在窗口顶部。默认值

    当top=false时,页面滚动,使elem出现在窗口底部。

9.5 禁止滚动

  • 禁止页面滚动:document.body.style.overflow = "hidden"
  • 取消禁止页面滚动:document.body.style.overflow = ""
  • 禁止元素滚动:把document.body换成elem元素即可

这个方法的缺点是会使滚动条消失。如果滚动条占用了一些空间,它原本占用的空间就会空出来,那么内容就会“跳”进去以填充它。

我们可以对比冻结前后的 clientWidth。如果它增加了(滚动条消失后),那么我们可以在 document.body 中滚动条原来的位置处通过添加 padding,来替代滚动条,这样这个问题就解决了。

9.6 小结

  1. 窗口的宽高:document.documentElement.clientWidth/Height
  2. 文档的完整宽高最好不要直接使用document.documentElement.scrollWidth/Height
  3. 读取当前的滚动:window.pageYOffset/pageXOffset。
  4. 更改当前的滚动:
    • window.scrollTo(pageX,pageY) — 绝对坐标,
    • window.scrollBy(x,y) — 相对当前位置进行滚动,
    • elem.scrollIntoView(top) — 滚动以使 elem 可见(elem 与窗口的顶部/底部对齐)。