我们如何找到浏览器窗口的宽度和高度?我们如何获取文档的完整宽度和高度,包括滚动出的部分?我们如何使用 JavaScript 滚动页面?
对于此类信息,我们可以使用根文档元素 document.documentElement
,它对应于 <html>
标记。但还需要考虑其他方法和特殊情况。
窗口的宽度/高度
要获取窗口宽度和高度,我们可以使用 document.documentElement
的 clientWidth/clientHeight
例如,此按钮显示您的窗口高度
window.innerWidth/innerHeight
浏览器还支持 window.innerWidth/innerHeight
等属性。它们看起来像我们想要的内容,那么为什么不使用它们呢?
如果存在滚动条,并且它占据了一些空间,则 clientWidth/clientHeight
会提供不包含它的宽度/高度(减去它)。换句话说,它们返回文档可见部分的宽度/高度,可用于内容。
window.innerWidth/innerHeight
包含滚动条。
如果存在滚动条,并且它占据了一些空间,那么这两行显示不同的值
alert( window.innerWidth ); // full window width
alert( document.documentElement.clientWidth ); // window width minus the scrollbar
在大多数情况下,我们需要可用窗口宽度才能在滚动条内绘制或定位某些内容(如果有),因此我们应该使用 documentElement.clientHeight/clientWidth
。
DOCTYPE
很重要请注意:当 HTML 中没有 <!DOCTYPE HTML>
时,顶级几何属性可能会有所不同。可能会出现奇怪的事情。
在现代 HTML 中,我们应该始终编写 DOCTYPE
。
文档的宽度/高度
从理论上讲,由于根文档元素是 document.documentElement
,并且它包含所有内容,因此我们可以将文档的完整大小测量为 document.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(错误 5991),其中我们应该使用 document.body
而不是 document.documentElement
。
幸运的是,我们根本不必记住这些特性,因为滚动可在特殊属性 window.pageXOffset/pageYOffset
中使用
alert('Current scroll from the top: ' + window.pageYOffset);
alert('Current scroll from the left: ' + window.pageXOffset);
这些属性是只读的。
window
属性scrollX
和scrollY
出于历史原因,这两个属性都存在,但它们是相同的
window.pageXOffset
是window.scrollX
的别名。window.pageYOffset
是window.scrollY
的别名。
滚动:scrollTo、scrollBy、scrollIntoView
要使用 JavaScript 滚动页面,其 DOM 必须完全构建。
例如,如果我们尝试使用<head>
中的脚本滚动页面,它将不起作用。
可以通过更改scrollTop/scrollLeft
来滚动常规元素。
我们可以使用document.documentElement.scrollTop/scrollLeft
对页面执行相同的操作(Safari 除外,在 Safari 中应使用document.body.scrollTop/Left
)。
或者,还有一个更简单、更通用的解决方案:特殊方法 window.scrollBy(x,y) 和 window.scrollTo(pageX,pageY)。
-
方法
scrollBy(x,y)
相对于其当前位置滚动页面。例如,scrollBy(0,10)
将页面向下滚动10px
。下面的按钮演示了这一点
-
方法
scrollTo(pageX,pageY)
将页面滚动到绝对坐标,以便可见部分的左上角具有相对于文档左上角的坐标(pageX, pageY)
。这就像设置scrollLeft/scrollTop
。要滚动到最开始,我们可以使用
scrollTo(0,0)
。
这些方法对所有浏览器的工作方式相同。
scrollIntoView
为了完整起见,我们再来介绍一个方法:elem.scrollIntoView(top)。
调用elem.scrollIntoView(top)
将滚动页面以使elem
可见。它有一个参数
- 如果
top=true
(这是默认值),则页面将滚动以使elem
出现在窗口顶部。元素的上边缘将与窗口顶部对齐。 - 如果
top=false
,则页面将滚动以使elem
出现在底部。元素的下边缘将与窗口底部对齐。
下面的按钮将页面滚动到位于窗口顶部的位置
此按钮将页面滚动到位于底部的位置
禁止滚动
有时我们需要让文档“不可滚动”。例如,当我们需要用一个需要立即注意的大消息覆盖页面时,我们希望访问者与该消息交互,而不是与文档交互。
要让文档不可滚动,只需设置 document.body.style.overflow = "hidden"
。页面将“冻结”在其当前滚动位置。
试试看
第一个按钮冻结滚动,而第二个按钮释放滚动。
我们可以使用相同技术冻结其他元素的滚动,而不仅仅是 document.body
。
该方法的缺点是滚动条消失了。如果它占用了空间,那么该空间现在是空闲的,并且内容“跳动”以填充它。
这看起来有点奇怪,但是如果我们在冻结前后比较 clientWidth
,则可以解决此问题。如果它增加了(滚动条消失了),则在滚动条的位置向 document.body
添加 padding
以保持内容宽度相同。
总结
几何
-
文档可见部分的宽度/高度(内容区域宽度/高度):
document.documentElement.clientWidth/clientHeight
-
整个文档的宽度/高度,包括滚动出的部分
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
可见(与窗口顶部/底部对齐)。
评论
<code>
标记,对于多行代码,请将其包装在<pre>
标记中,对于超过 10 行的代码,请使用沙盒 (plnkr、jsbin、codepen…)