我们如何找到浏览器窗口的宽度和高度?我们如何获取文档的完整宽度和高度,包括滚动出的部分?我们如何使用 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…)