在开发中我们常常会用到判断滚动条是否触底的逻辑。我一般都会在网上搜一段代码,这段代码有用到scrollTop、clientHeight、 scrollHeight 。接着我简单看一下好像理解了,再在项目里用一下好使了就没去深入研究相关概念。等下次用到了还是搜一下,自己写不出来…于是笔者想想深入研究一下这些概念好摆脱尴尬的局面。

看了很多的文章,感觉有一些写的不够详细具体,要么就是概念的堆砌没有例子和图,要么就是一张图写满了各种概念不易于理解。于是笔者自己对照MDN文档总结了一下这些概念,并结合示例加深对这些概念的理解,并总结了这些概念彼此之间的数量关系和应用场景。欢迎大家阅读,有写错或者理解错的地方请不吝指正。

1.clientWidth、clientHeight、clientLeft、clientTop

1.1 clientWidth

(1)含义:只读属性,表示元素的内部宽度,单位为像素。

(2)从盒子模型角度看:包含padding,但不包含border, margin 以及垂直滚动条。

(3)注意:内联元素clientWidth为0。

(4)语法:element.clientWidth;

1.2 clientHeight

(1)含义:只读属性,表示元素的内部高度,单位为像素。

(2)从盒子模型角度看:包含padding,但不包含border, margin 以及水平滚动条。

(3)注意:内联元素clientHeight为0。

(4)语法:element.clientHeight;

1.3 clientLeft

(1)含义:只读属性,表示一个元素左边框的宽度,单位为像素。

(2)从盒子模型角度看:clientLeft 不包括左外边距和左内边距.

(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)然后在 Eelments->Computed 看盒模型:

(3)查看clientWidth的值:

clientWidth计算:内容宽度+左右padding即 182+28*2 = 182 + 56 = 238

(4)查看clientHeight的值:

clietentHeight计算:内容高度+上下padding即 102 + 0 = 102

(5)查看clientLeft和clientTop值:

clientLeft和clientTop计算:左边框 24 ; 上边框24

注意以上的计算过程是笔者在盒模型的设置为:box-sizing: content-box时的计算方法,如果盒模型设置为 box-sizing: border-box; 则计算clientWidth 和 clientHeight的方法为:

(1)clientWidth :clientWidth 可以通过 CSS width+ CSS padding - 垂直滚动条宽度 (如果存在) 来计算

(2)clientHeight:clientHeight 可以通过 CSS height + CSS padding - 水平滚动条高度 (如果存在) 来计算

以clientWidth的计算为例说明一下

首先按照正常算法计算: 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)备注:各浏览器的 offsetWidth 可能有所不同。

2.2 offsetHeight

(1)含义:只读属性,元素的布局高度,单位像素。

(2)从盒子模型角度看:包含通过css设置的height, border, padding以及水平方向滚动条的高度。

(3)语法:element.offsetHeight

(4)备注:如果元素被隐藏则返回0。

接下来要介绍offsetLeft和offsetTop的含义,在这之前要明白offsetParent的含义:

HTMLElement.offsetParent 是一个只读属性。
返回一个指向最近的(指包含层级上的最近)包含该元素的定位元素或者最近的 table,td,th,body元素。
当元素的 style.display 设置为 "none" 时,offsetParent 返回 null

2.3 offsetLeft

(1)含义:只读属性,当前元素左上角相对于offsetParent左边界的偏移。

(3)语法:element.offsetLeft

(4)备注:如果元素被隐藏则返回0。

2.4 offsetTop

(1)含义:只读属性,当亲元素相对于offsetParent元素的顶部内边距的距离。

(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)查看offsetWidth的值

其计算过程:border 20 + pading 20 + content 183 + 滚动条 17 = 240。也就是: 20 + 20 + 200= 240

如果设置 box-sizing:border-box 则对应的盒子模型变为:

此时查看offsetWidth的值:

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

发现虽然computed的盒子模型显示padding是10 ,但实际上并不是10了,而且由于滚动条的存在左右显示的padding所占空间已经不相等。

(3)读取offsetHeight值

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

(4)读取offsetTop和offsetLeft的值

如上我们发现offsetParent为body元素, 那么offsetTop值为59 , offsetLeft的值为29,都是怎么算出来的啊?看一下body以及class为parent的外层div的盒模型结构:

参考盒子模型结构我们可以得到计算过程:

offsetTop : 8 (body padding) + 1 (parent border) +50 (parent padding) = 59

offsetLeft: 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) ,那么滚动条会位于最右侧(内容开始处),并且scrollLeft值为 0。此时,当你从右到左拖动滚动条时,scrollLeft 会从 0 变为负数。

3.2 scrollTop

(1)含义:可读取可设置,一个元素的内容垂直滚动的像素数。

(2)语法:Element.scrollTop

(3)备注:一个元素的 scrollTop 值是这个元素的内容顶部(卷起来的)到它的视口可见内容(的顶部)的距离的度量。注意,这里并没有描述为滚动条距离顶部的距离,当然这样理解也没问题。当一个元素的内容没有产生垂直方向的滚动条,那么它的 scrollTop 值为0。

3.3 scrollWidth

(1)含义:只读属性,是一个元素内容宽度的度量,包括由于溢出导致的视图不可见内容。

(2)语法:Element.scrollWidth

(3)备注:没有水平滚动条的情况下,scrollWidth 值与元素视图填充所有内容所需要的最小值clientWidth相同。

3.4 scrollHeight

(1)含义:只读属性,是一个元素内容高度的度量,包括由于溢出导致的视图不可见内容。

(2)语法:element.scrollHeight

(3)备注:没有垂直滚动条的情况下,scrollHeight 值与元素视图填充所有内容所需要的最小值clientHeight相同。

为了说明scrollHeight 的含义,MDN文档给出了如下的示意图:

3.5 示例演示

示例代码任然沿用2.5 节的demo示代码, 运行效果如下:

(1)查看scrollLeft的值

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

如上图所示:水平方向滚动条向右滚动了一定距离,则此时scrollLeft的值为58。

(2)查看scrollTop的值

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

如上图所示:竖直方向上滚动条没有向下滚动了一定距离,则此时scrollTop的值为59。

(3)查看crollWidth的值

如上图所示:scrollWidth的值为704,代表内容的宽度。

(4)查看scrollHeight的值

如上图所示:scrollHeight的值为262,代表内容的高度。

4.彼此之间的数量关系以及应用

(1)关系1

没有竖直方向上的滚动条: scrollHeight = clientHeight

应用:判断竖直方向是是否有滚动条

(2)关系2

没有水平方向上的滚动条:scrollWidth = clientWidth

应用:判断水平方向是否有滚动条

(3)关系3

scrollTop + clientHeight >= scrollHeight

因为scrollTop是一个非整数,而scrollHeight和clientHeight是四舍五入的,因此确定滚动区域是否滚动到底的唯一方法是查看滚动量是否足够接近某个阈值:

Math.abs(element.scrollHeight - element.clientHeight - element.scrollTop) < 1

5.总结

一图胜千言,本文的全部内容如下:

scrollTop、clientHeight、 scrollHeight...学完真的理解了相关推荐

  1. 滚动条三要素scrollTop clientHeight scrollHeight

    插件 https://github.com/inuyaksa/jquery.nicescroll <!DOCTYPE html> <html><head><m ...

  2. 程序员学完深入理解计算机系统,深入理解计算机系统9个重点笔记

    编写高效的程序需要下面几类活动:选择1组适合的算法和数据结构.这是很重要的,好的数据结构有时能帮助更快的实现某些算法,这也要求编程人员能够熟知各种经常使用的数据结构和算法. 编写出使编译器能够有效优化 ...

  3. Js——ScrollTop、ScrollHeight、ClientHeight、OffsetHeight汇总

    一直对ScrollTop.ScrollHeight.ClientHeight.OffsetHeight这些内容傻傻分不清楚,今天整体下. scrollHeight scrollHeight含有scro ...

  4. 软件工程作业2.1:阐述对软件工程的理解,学完这门课自己能学到什么,学完后能做什么...

    对软件工程这门课的理解 软件工程是把系统的.有序的.可量化的方法应用到软件的开发.运营和维护上的过程.在软件工程中,远远不止很多人以为的只是单纯地进行软件开发,其实真正的软件开发的时间只是软件工程中的 ...

  5. 关于offsetTop offsetHeight clientHeight scrollHeight scrollTop的区别研究

    我是以chrome浏览器做的研究. 先看一段代码: <script>window.addEventListener('DOMContentLoaded',function(){var no ...

  6. python人工智能入门纳米学位_最近看到udacity的纳米学位很火,号称学完可以找到工作了,这是真的吗?...

    2018年二月更新: 刷完了Coursera的Deep Learning Specialization,Coursera吃了大约二十几门Coding.Data Science的硬课(包括传说中的PGM ...

  7. 单词不用背,学完自然会!”这个方法,你知道越早越好!

    似乎身边总有这么一类"神人",他们总说:"我学英语从来不背单词." 如果你信了,那你十有八九被忽悠了,这就和上学时总考98分的学霸,每次都说自己没复习一样-- ...

  8. python可以从事什么工作-学完Python开发可以从事哪些行业?

    Python开发培训前景如何?现在互联网巨头,都已经转投到人工智能领域,而人工智能的首选编程语言就是python,未来前景显而易见. 无论是学习任何一门语言,基础知识,就是基础功非常重要,找一个有丰富 ...

  9. 学完计算机还是不懂,如果看了这篇文章你还不懂傅里叶变换,那就过来掐死我吧...

    如果看了这篇文章你还不懂傅里叶变换,那就过来掐死我吧(二) Heinrich ·  15 天前 已于2014.6.6更新,地址:傅里叶分析之掐死教程(完整版)更新于2014.06.06 - 与时间无关 ...

  10. 爬虫爬出来的数据不全_斥巨资学完Python数据分析后,给运营人总结7个小建议...

    曾经我们看不起满大街卖英语课的销售,现在朋友圈一个广告就屁颠屁颠报名学Python,堪称年度迷惑行为之一. 难得摊上一个风口浪尖的话题,亲身经历的我也算是抓到一个写作素材了. 去年十一月开始学数据分析 ...

最新文章

  1. 取消掉Transfer-Encoding:chunked
  2. Java 运行时数据区域,哪些是线程隔离的?哪些又是公有的?
  3. shell 批量添加用户健壮版
  4. 构建之法:1、2、3章阅读后感
  5. nb-iot 华为云_海曼NB-IoT智慧消防解决方案通过华为云资格审核,正式入驻华为云市场...
  6. 获取textarea每一行的内容_PLC编程的基本原则和方法,64页内容介绍PLC编程,值得收藏...
  7. 【商品架构day8】京东几百亿的商品怎么搜索
  8. linux不支持tailf指令,Linux安装tailf
  9. “美国人工智能倡议”解读
  10. mybatis事务原理与集成spring的事务原理
  11. 自然语言处理——中英文分词工具(还可做词性标注与命名实体识别)
  12. 解决:Linux nohup命令不再默认输出日志文件
  13. SaltStack常用的模块-1
  14. win10下安装多个JDK配置方法
  15. 练习2-4:重新编写函数squeeze(s1,s2),将字符串s1中的任何字符与字符串时s2中的字符匹配的字符都删除
  16. 计算机主机内部的除尘课件,怎么给电脑主机机箱内部除尘
  17. 纯javascript实现赛车小游戏
  18. 异步调用RFC:CALL FUNCTION ‘ZXXXXXXXXX‘ IN UPDATE TASK
  19. 遥感资源大放送(上):用开源代码,训练土地分类模型
  20. 除了北上广深杭,还有哪些城市移动互联网发展的不错

热门文章

  1. HowNet介绍及相关API的使用方法
  2. 图片类word报告生成器
  3. 19个免费好用的CSS代码样式生成器工具
  4. 三菱PLC通用快捷键
  5. html网页简单代码
  6. 共享单车项目计划书_2020年共享单车商业计划书模板
  7. 详解web网站测试的内容以及步骤
  8. labview与C数据类型的对应关系
  9. layui文档,最新文档地址,官网已经下线
  10. 2019年美赛建模D题解题思路