文章目录

  • 各属性详解
    • 实现
  • offsetParent、offsetLeft/offsetTop深度剖析
  • element.offsetParent
    • 定义
    • 祖先元素中不存在定位元素
    • webkit内核、Firefox下的特殊情况
  • element.offsetWidth / element.offsetHeight
    • 定义
  • element.offsetLeft / element.offsetTop
    • 定义
    • element在正常文档流中
      • element与element.offsetParent之间存在浮动元素
    • element脱离文档流

每个HTML元素都具有clientHeight offsetHeight scrollHeight offsetTop scrollTop 这5个和元素高度、滚动、位置相关的属性,单凭单词很难搞清楚分别代表什么意思之间有什么区别。通过阅读它们的文档总结出规律如下:

各属性详解

clientHeight和offsetHeight属性和元素的滚动、位置没有关系它代表元素的高度,其中:
clientHeight:包括padding但不包括border、水平滚动条、margin的元素的高度。对于inline的元素这个属性一直是0,单位px,只读元素。

offsetHeight:包括padding、border、水平滚动条,但不包括margin的元素的高度。对于inline的元素这个属性一直是0,单位px,只读元素。

接下来讨论出现有滚动条时的情况:
当本元素的子元素比本元素高且overflow=scroll时,本元素会scroll,这时:
scrollHeight: 因为子元素比父元素高,父元素不想被子元素撑的一样高就显示出了滚动条,在滚动的过程中本元素有部分被隐藏了,scrollHeight代表包括当前不可见部分的元素的高度。而可见部分的高度其实就是clientHeight,也就是scrollHeight>=clientHeight恒成立。在有滚动条时讨论scrollHeight才有意义,在没有滚动条时scrollHeight==clientHeight恒成立。单位px,只读元素。

scrollTop: 代表在有滚动条时,滚动条向下滚动的距离也就是元素顶部被遮住部分的高度。在没有滚动条时scrollTop==0恒成立。单位px,可读可设置。
offsetTop: 当前元素顶部距离最近父元素顶部的距离,和有没有滚动条没有关系。单位px,只读元素。
offsetTop: 当前元素顶部距离最近父元素顶部的距离,和有没有滚动条没有关系。单位px,只读元素。

  • 网页可见区域高:document.body.clientHeight //返回元素的高度(包括元素高度、内边距,不包括边框和外边距)

  • 网页正文全文高:document.body.scrollHeight //返回元素的高度(包括元素高度、内边距和溢出尺寸,不包括边框和外边距),无溢出的情况,与clientHeight相同

  • 网页可见区域高(包括边线的高):document.body.offsetHeight //返回元素的高度(包括元素高度、内边距和边框,不包括外边距)

  • scrollTop //此属性可以获取或者设置对象的最顶部到对象在当前窗口显示的范围内的顶边的距离,也就是元素滚动条被向下拉动的距离。 返回值是一个整数,单位是像素。此属性是可读写的

  • 网页被卷去的高:document.body.scrollTop

  • 屏幕分辨率高:window.screen.height

  • style.height //返回元素的高度(包括元素高度,不包括内边距、边框和外边距)

  • offsetTop //返回元素的上外缘距离最近采用定位父元素内壁的距离,如果父元素中没有采用非静态定位的,则是获取上外边缘距离body的距离。


下面是理解应用
(在IOS移动端上,当使用overflow: scroll;属性时,滚动效果慢且不流畅,该情况可以使用

-webkit-overflow-scrolling: touch;属性,让滚动条产生回弹效果,增加滚动的流畅性,提高用户的体验。)。在手指在移动设备的触摸屏上滑动的过程中,监听手指开始滑动,滑动过程中及滑动结束3个事件。在滑动中事件中检查当前滑动的位置是否到达滚动区域的底部,若已到达底部则停止滑动。

实现

给滑动区域添加手势触摸的相关事件

<div @touchstart="touchStart" @touchmove="touchMove" @touchEnd="touchEnd"><!-- 这是一个滚动区域 -->
</div>

定义一个变量用来记录上一次手势滑动过程中最新位置的纵坐标值

export default {data () {lastScrollY: 0 // 上一次手势滑动过程中最新位置的纵坐标}
}

通过手势滑动过程中出发的事件监听滚动区域是否已经到达底部

export default {methods: {touchStart(e) {// 滑动开始时记录起始位置纵坐标this.lastScrollY = e.touches[0].clientY},touchMove(e) {// 滑动过程中记录当前位置纵坐标let top = e.touches[0].clientY// 当前滚动条距离顶部的距离let scrollTop = e.currentTarget.scrollTop// 判断滚动条滚动的方向let direction = (this.lastScrollY - top) < 0 ? 'up' : 'down'// (若滚动条距离顶部的距离 >= 滚动区域的高度 - 滚动可视区域的高度) && 滚动条滚动方向向下 :已到达滚动区域的底部if (scrollTop >= (e.currentTarget.scrollHeight - e.currentTarget.offsetHeight) && direction === 'down') {// 取消事件的默认行为e.preventDefault()// 还原记录的坐标值this.lastScrollY = 0} else {// 否则更新记录的当前位置纵坐标this.lastScrollY = top}},touchEnd() {// 每一次滑动结束时还原记录的坐标值this.lastScrollY = 0}}
}

offsetParent、offsetLeft/offsetTop深度剖析

element.offsetParent

定义

element.offsetParent为包含element的祖先元素中,层级最近的定位元素。 也就是说,offsetParent必须满足三个条件:

  • 是element的祖先元素
  • 最靠近element
  • 是定位元素,即position属性不为static
<div class="position-outer" style="position: relative;"><div class="position" style="postion: relative;"><div class="not-position"><div class="box"></div></div></div>
</div>

打印box元素的offsetParent:

由此可见,box祖先元素中存在:

  • 层级为3的定位元素 position-outer
  • 层级为2的定位元素 position-inner
  • 层级为1的非定位元素 not-position

position-inner是同时满足层级最近和定位两个条件的。

祖先元素中不存在定位元素

<div class="box"></div>

webkit内核、Firefox下的特殊情况

  • element自身的display属性为none
<div class="position-outer" style="position: relative;"><div class="position-inner" style="postion: relative;"><div class="not-position"><div class="box" style="display: none;"> <!-- 注意这里! --></div></div></div>
</div>

  • element自身的position属性为fixed
<div class="position-outer" style="position: relative;"><div class="position" style="postion: relative;"><div class="not-position"><div class="box" style="position: fixed;"> <!-- 注意这里! --></div></div></div>
</div>

element.offsetWidth / element.offsetHeight

定义

offsetWidth = content + (垂直滚动条的宽度) + padding + border

  • 无滚动条情况下
<div class="box" style="">
</div>
.box {width: 200px;height: 100px;padding: 20px;border: 12px solid red;margin: 25px;
}

打印element.offsetWidth:

offsetWidth = 200(content) + 20 * 2(padding) + 12 * 2(border) = 264

  • 有滚动条情况下

可以看到,滚动条包含在padding中,因此,offsetWidth与在无滚动条情况下,大小不变。

element.offsetLeft / element.offsetTop

定义

element左上角相对于offsetParent左边界的偏移值。

有个疑问? element的左上角 与 offsetParent的左边界如何定义?是content-box、padding-box还是margin-box?

<div class="position"><div class="box"></div>
</div>
.position {position: relative;top:  0;left:  0;width: 400px;height: 200px;padding:  35px;border: 15px solid purple;
}.box {width: 200px;height: 100px;padding: 20px;border:  12px solid red;margin:  25px;
}

很明显,box的offsetParent为postion

打印box.offsetLeft和box.offsetTop:

在文档流中,box的整个margin-box是在position的content-box中的,由此可猜测:

box.offsetLeft = position.paddingLeft + box.marginleft = 35 + 25 = 60

真的是这样吗?其实并没有那么简单,需要分两种情况讨论:

element在正常文档流中

element.offsetLeft是指element的border-box左上角相对offsetParent的content-box的偏移量

由于position: relative的元素并没有脱离文档流,因此,也需要加入到offseLeft/offsetTop的计算中

修改box css属性:

.box {position: relative; /* 新增的 */top: 31px;          /* 新增的 */left: 31px;         /* 新增的 */width: 200px;height: 100px;padding: 20px;border:  12px solid red;margin:  25px;
}

再次打印box.offsetLeft和box.offsetTop:

两者的值都增加了31,也就是top和left属性对应的值,由此更新计算公式:

element.offsetLeft = offsetParent.paddingLeft + element.left + element.marginLeft

但是,以上都是在最简单的情况下计算的,即element与element.offsetParent之间没有其它层级的元素存在!

我们在element与element.offsetParent之间再插入一个元素:

<div class="position"><div class="middle">    <!-- 新增的 --><div class="box"></div></div>
</div>.parent {width: 30px;height: 150px;padding:  11px;border:  12px solid pink;margin-left:  13px;
}

打印box.offsetLeft和box.offsetTop:

两者的值又变化了!相比上次又增加了36,正好是parent的marginLeft、borderLeft 、paddingLeft之和,11 + 12 + 13 = 36,由此得到最终的计算公式:

element.offsetLeft = offsetParent.paddingLeft + element.left + element.marginLeft + (element与element.offsetParent之间所有 在正常文档流且position属性不为relative的元素 marginLeft、borderLeft、paddingLeft之和)

element与element.offsetParent之间存在浮动元素

现在,我们让parent向右浮动:

.parent {float: right;width: 30px;height: 150px;padding:  11px;border:  12px solid pink;margin-left:  13px;
}

打印box.offsetLeft和box.offsetTop:

这次只有box.offsetLeft变化了,而且也可以猜测到是由于parent的右浮,box是其子元素,一起右浮,导致box.offsetLeft变化的。

这下要怎么计算?难道还要算浮动的距离吗?

并不需要!只要借助parent就能计算!仔细想想,element与element.offsetParent一定是没有浮动元素的,那么对于parent,其offsetParent也就是box的offsetParent,即postition。

我们打印下parent.offsetleft:

再计算box到parent之间的偏移量: box.left + box.marginLeft + parent.paddingLeft + parent.borderLeft + parent.marginLeft = 31 + 25 + 11 + 12 + 13 = 92

76 + 92 = 168,与box.offsetLeft一致,这也说明我们的计算公式是正确的!

element脱离文档流

也就是说element的display属性为absolute或fixed,由于fixed会导致offsetParent为null,所以我们将box的display设置为absolute:

<div class="position"><div class="box"></div>
</div>
复制代码
.box {position: absolute; /* 新增的 */top: 31px;left:  31px;width: 200px;height: 100px;padding: 20px;border:  12px solid red;margin:  25px;
}.position {position: relative;top:  0;left:  0;width: 400px;height: 200px;padding:  35px;border: 15px solid purple;
}

打印box.offsetLeft和box.offsetTop:

我们知道,display属性为absolute或fixed的元素,是相对于包含块的padding-box定位的,因此在计算offsetLeft时,就不需要考虑offsetParent的paddingLeft了。

并且,element是脱离文档流的,也就是说,除了element.offsetParent,不再与其它任何元素产生联系,也就不需要再考虑element与element.offsetParent之间的任何元素了。

因此,计算公式非常简单:

element.offsetLeft = element.left + element.marginLeft

评论1:

纠正一下,插入完parent元素后,box的offsetTop值应为114px,因为parent元素并没有margin-top值,而浮动之后的parent.offsetLeft应为89px,它已经包含了parent元素的margin-left值(13px),再看插入parent后,box的offsetLeft为127px(margin-left的值计算在内),将127px-13px+54px( 89px - 35px(position的padding值) )=168px这就为浮动之后的box的offsetLeft的值。
转载自

clientHeight offsetHeight scrollHeight offsetTop scrollTop相关推荐

  1. clientHeight.offsetHeight.scrollHeight等的区别

    查看了博文http://www.cnblogs.com/fullhouse/archive/2012/01/16/2324131.html 然后自己写一下加深印象. clientHeight:可见高度 ...

  2. clientHeight,offsetHeight,scrollHeight迷一样的三个值

    https://blog.csdn.net/qq_39083004/article/details/78498178 https://www.imooc.com/article/17571  推荐 o ...

  3. offsetTop,offsetHeight,scrollHeight,scrollTop的区别

    offsetTop,offsetHeight,scrollHeight,scrollTop,这些属性曾经困扰了我很长很长很长时间. 今天花点功夫,彻底把他们搞清楚了. 假设 obj 为某个 HTML ...

  4. clientHeight、offsetHeight、scrollHeight、scrollTop

    由于长时间对clientHeight.offsetHeight.scrollHeight.scrollTop这几个js-dom不理解,处于半迷糊状态,现在就仔仔细细实验整理一波,希望能做个总结,方便以 ...

  5. 【javascript】clientHeight,offsetHeight,scrollHeight,scrollTop的理解,以及触底函数

    1.clientHeight 含义:元素的像素高度,包含元素的高度+内边距,不包含水平滚动条,边框和外边距 图示: 2.offsetHeight 含义:元素的像素高度 包含元素的垂直内边距和边框,水平 ...

  6. clientHeight ,offsetHeight,style.height,scrollHeight有区别与联系

    style.height 包括 元素的滚动条,不包括边框 clientHeight 不包括元素的滚动条和边框,只有在没有元素的滚动条的情况下,style.height相等于clientHeight o ...

  7. 关于height、offsetheight、clientheight、scrollheight、innerheight、outerheight的区别

    二.也是平时经常用到的offsetheight 它返回的高度是内容高+padding+边框,但是注意哦,木有加margin哦,当然一般也木有啥需要把margin加进去的,以上代码为例,结果显示上图h2 ...

  8. offsetHeight, clientHeight与scrollHeight的区别

    [size=xx-large][color=indigo]offsetHeight, clientHeight与scrollHeight的区别[/color][/size] [size=large][ ...

  9. JS中clientHeight、scrollHeight和offsetHeight的大坑,滚动条抖动问题解决

    JS中clientHeight.scrollHeight和offsetHeight的大坑,滚动条抖动问题解决 1.什么是clientHeight.scrollHeight和offsetHeight 1 ...

最新文章

  1. ScriptManager 帮助您实现 Web 应用程序的 AJAX 功能
  2. Raspberry 4B安装wiringPi库 和 python-dev包
  3. 删除Windows 系统快捷方式箭头 Delete Windows Shortcuct Arrows
  4. Qt Creator使用3D材质
  5. nginx集群tomcat,session共享问题
  6. Spring差缺补漏
  7. 2019 中国.NET 开发者峰会正式启动
  8. java创建临时文件_用Java创建一个临时文件
  9. Go编译exe可执行文件去掉运行时的CMD窗口
  10. 中国农业病虫害防治行业市场供需与战略研究报告
  11. md5 加密 swfit版
  12. 模块是python中普通的文件吗_python 包和模块
  13. python 查找excel内容所在的单元格_使用Python查找Excel单元格引用
  14. css元素居中的几种方式
  15. jquery.countdown.js 使用教程_2020年建筑教程资源近2000G免费建筑教程,分享给有需要的建筑同行...
  16. ROS入门教程(一)
  17. Excel表格如何筛选重复内容(筛选重复数据的方法)
  18. 泰晤士报华科计算机排名,最新USNews中国内地高校计算机学科排名,北大第7,华科第2?...
  19. 2021毓英中学高考成绩查询,泉州知名中学2020高考成绩喜报龙虎榜
  20. 阿里云服务器从购买到配置全攻略

热门文章

  1. 跳过微信屏蔽APP扫描以及识别不同系统的手机
  2. 北京java研发平均工资_各地java开发工程师平均工资 北京高级java开发工程师工资2万多...
  3. 小波变换:基于matlab的数字图像水印嵌入及提取(灰度图)
  4. animate动画插件的简单运用
  5. 使用字符映射完成简单的对称加密
  6. 三菱FX5U传送指令
  7. U²-Net:使用显著性物体检测来生成真实的铅笔肖像画
  8. 参考爆料英特尔i5-10400f和i5-10400区别?哪个好?深度爆料评测
  9. 用telnet+openocd+jtag_dpi+vcs仿真调试RISCV的cpu
  10. 1.回文是指正读和反读均相同的字符序列,如“abba”和“abdba”均是回文,但“good”不是回文。试写一个算法判定给定的字符向量是否为回文。(提示:将一半字符入栈。)2.假设以带头结点的循环链