本文主要是介绍clientHeight offsetHeight scrollHeight offsetTop scrollTop,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- 各属性详解
- 实现
- 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的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!