本文深入解析JavaScript中判断滚动条触底的常用属性:scrollTop、clientHeight与scrollHeight。通过对比clientWidth/Height、offsetWidth/Height以及scroll系列属性的定义、计算方式及盒模型差异,结合具体代码示例与数值验证,阐明各属性的实际含义。文章最后总结各属性间的数量关系,并提供判断滚动到底部的精确逻辑与代码实现,帮助开发者摆脱盲目复制代码的困境,准确掌握滚动检测原理。
引言
在Web开发过程中,判断页面或容器滚动条是否触底是一项常见需求。许多开发者习惯直接搜索现成代码,其中通常涉及、以及等属性。虽然初步查看似乎能理解,且在实际项目中能运行,但由于缺乏对底层概念的深入探究,导致再次遇到类似需求时仍需重新搜索,无法独立编写相关逻辑。为了摆脱这种被动局面,有必要对这些概念进行系统性的深入研究。
市面上许多相关教程存在概念堆砌、缺乏实例或图表说明不清晰等问题,导致理解困难。为此,本文对照MDN官方文档,重新梳理了这些核心概念,并结合具体示例进行图解说明,旨在帮助读者建立清晰的概念体系,总结各属性间的数量关系及其典型应用场景。欢迎读者阅读指正,如有理解偏差之处,敬请批评指正。
1.clientWidth、clientHeight、clientLeft、clientTop
1.1 clientWidth
(1)含义:这是一个只读属性,表示元素内部的宽度,单位为像素。
(2)从盒子模型角度分析:该值包含内边距(padding),但不包含边框(border)、外边距(margin)以及垂直滚动条的宽度。
(3)注意事项:对于内联元素,的值始终为0。
(4)语法:element.clientWidth;

1.2 clientHeight
(1)含义:这是一个只读属性,表示元素内部的高度,单位为像素。
(2)从盒子模型角度分析:该值包含内边距(padding),但不包含边框(border)、外边距(margin)以及水平滚动条的高度。
(3)注意事项:对于内联元素,的值始终为0。
(4)语法:element.clientHeight;
1.3 clientLeft
(1)含义:这是一个只读属性,表示元素左侧边框的宽度,单位为像素。
(2)从盒子模型角度分析:不包含左侧外边距和左侧内边距。
(3)语法:element.clientLeft
(4)备注:如果元素的文本方向为从右向左(RTL, right-to-left),且因内容溢出导致左侧出现垂直滚动条,则该属性值将包含该滚动条的宽度。
1.4 clientTop
(1)含义:这是一个只读属性,表示元素顶部边框的宽度,单位为像素。
(2)从盒子模型角度分析:不包含顶部外边距或内边距。
(3)语法:element.clientTop
1.5 示例演示
以下列盒子模型为例进行验证,观察各属性值及其计算过程(示例源自MDN,建议读者打开浏览器控制台亲自测试):
(1)首先在控制台获取DOM元素:
const div = document.getElementById('iddiv')
(2)随后在Elements面板的Computed视图中查看盒模型:

(3)查看的值:

计算:内容宽度加上左右内边距,即 182 + 28*2 = 182 + 56 = 238
(4)查看的值:

计算:内容高度加上上下内边距,即 102 + 0 = 102
(5)查看和的值:

和计算:左边框宽度为 24;上边框宽度为 24
注意:上述计算基于盒模型设置为box-sizing: content-box的情况。若盒模型设置为box-sizing: border-box;,则计算和的方法将发生变化:
(1):可通过 CSS width 加上 CSS padding 再减去垂直滚动条宽度(若存在)来计算。
(2):可通过 CSS height 加上 CSS padding 再减去水平滚动条高度(若存在)来计算。
以的计算为例进行说明:


首先按常规算法计算: 95 + 28*2 = 95 + 56 = 151。由于151大于134,差额部分即为滚动条宽度,计算得 151 - 134 = 17。经测量,滚动条宽度确实为17,如下图所示:

2.offsetWidth、offsetHeight、offsetLeft、offsetTop
2.1 offsetWidth
(1)含义:这是一个只读属性,返回元素的布局宽度,单位为像素。
(2)从盒子模型角度分析:该值包含CSS设置的width、边框(border)、内边距(padding)以及竖直方向滚动条的宽度。
(3)语法:element.offsetWidth
(4)备注:不同浏览器对的计算可能存在差异。
2.2 offsetHeight
(1)含义:这是一个只读属性,表示元素的布局高度,单位为像素。
(2)从盒子模型角度分析:该值包含CSS设置的height、边框(border)、内边距(padding)以及水平方向滚动条的高度。
(3)语法:element.offsetHeight
(4)备注:如果元素被隐藏,则返回0。
接下来介绍和的含义,在此之前需要明确的概念:
是一个只读属性。
它返回一个指向包含当前元素的最近定位元素(ancestor),或者最近的table、td、th或body元素的引用。
当元素的style.display被设置为"none"时,返回null。
2.3 offsetLeft
(1)含义:这是一个只读属性,表示当前元素左上角相对于左边界的偏移量。
(3)语法:element.offsetLeft
(4)备注:如果元素被隐藏,则返回0。
2.4 offsetTop
(1)含义:这是一个只读属性,表示当前元素相对于元素顶部内边距的距离。
(3)语法:element.offsetTop
(4)备注:如果元素被隐藏,则返回0。
2.5 示例演示
笔者编写了一个demo来说明上述概念,代码如下:
<html lang="en">
<head>
<style>
.parent {
width: 400px;
height: 400px;
border: 1px solid #ccc;
padding-top: 50px;
padding-left: 20px;
}
.child {
width: 200px;
height: 200px;
padding: 10px;
border: 10px solid black;
overflow: auto;
}
</style>
</head>
<body>
<div class="parent">
<div class="child" id="child-id">
<!-- 省略内部内容 -->
</div>
</div>
</body>
</html>
代码运行效果及盒模型如下图所示:


(1)获取内部div的DOM元素
const div = document.getElementById('child-id')
(2)查看的值

其计算过程:border 20 + padding 20 + content 183 + 滚动条 17 = 240。
即: 20 + 20 + 200 = 240
如果设置box-sizing:border-box ,则对应的盒模型变为:

此时查看的值:

其计算过程:content 160 + padding 20 + border 20 = 200。观察实际效果:


发现虽然Computed视图中的盒模型显示padding为10,但实际上并非如此,且由于滚动条的存在,左右显示的padding所占空间已不相等。
(3)读取值


计算过程与类似: 183 content + 17 滚动条 + 20 padding + 20 border = 240。如果设置box-sizing:border-box ,则值如下:

(4)读取和的值

如上所述,为body元素,那么值为59,值为29,具体计算方式如下?查看body及class为parent的外层div的盒模型结构:


参考盒模型结构,我们可以得到计算过程:
: 8 (body padding) + 1 (parent border) + 50 (parent padding) = 59
: 8 (body padding) + 1 (parent border) + 20 (parent padding) = 29
3.scrollLeft、scrollTop、scrollWidth、scrollHeight
3.1 scrollLeft
(1)含义:可读取也可设置,表示元素内容水平滚动的像素数(即滚动条距离元素左侧的距离)。
(2)语法:Element.scrollLeft
(3)备注:注意,如果元素内容排列方向为rtl(right-to-left),滚动条将位于最右侧(内容起始处),此时值为0。当从右向左拖动滚动条时,值会从0变为负数。
3.2 scrollTop
(1)含义:可读取也可设置,表示元素内容垂直滚动的像素数。
(2)语法:Element.scrollTop
(3)备注:元素的值表示元素内容顶部(卷起部分)到其视口可见内容顶部的距离。虽然可以理解为滚动条距离顶部的距离,但更准确的理解是内容偏移量。当元素未产生垂直滚动条时,值为0。
3.3 scrollWidth
(1)含义:这是一个只读属性,表示元素内容的宽度,包括因溢出而不可见的部分。
(2)语法:Element.scrollWidth
(3)备注:在没有水平滚动条的情况下,值与填满内容所需的最小宽度相同。
3.4 scrollHeight
(1)含义:这是一个只读属性,表示元素内容的高度,包括因溢出而不可见的部分。
(2)语法:element.scrollHeight
(3)备注:在没有垂直滚动条的情况下,值与填满内容所需的最小高度相同。
为了说明的含义,MDN文档提供了如下示意图:

3.5 示例演示
示例代码仍沿用2.5节的demo代码,运行效果如下:
(1)查看的值


如上图所示:水平方向滚动条未向右滚动时,的值为0。


如上图所示:水平方向滚动条向右滚动了一定距离,此时的值为58。
(2)查看的值


如上图所示:竖直方向滚动条未向下滚动时,的值为0。


如上图所示:竖直方向滚动条向下滚动了一定距离,此时的值为59。
(3)查看的值


如上图所示:的值为704,代表内容的总宽度。
(4)查看的值


如上图所示:的值为262,代表内容的总高度。
4.彼此之间的数量关系以及应用
(1)关系1
没有竖直方向上的滚动条: =
应用:判断竖直方向是否存在滚动条
(2)关系2
没有水平方向上的滚动条: =
应用:判断水平方向是否存在滚动条
(3)关系3
+ >=
由于可能为非整数值,而和经过四舍五入处理,因此确定滚动区域是否滚动到底部的唯一可靠方法是检查滚动量是否足够接近某个阈值:
Math.abs(element.scrollHeight - element.clientHeight - element.scrollTop) < 1
5.总结
一图胜千言,本文的全部内容总结如下:

以上就是JS属性scrollTop clientHeight scrollHeight理解学习的详细内容,更多关于JS属性scrollTop clientHeight scrollHeight的资料请关注本站其它相关文章!