这是我参与「掘金日新计划 · 8 月更文挑战」的第3天,点击查看活动详情
offsetParent
offsetParent 是一个只读属性,返回一个指向最近的(指包含层级上的最近)包含该元素的定位元素或者最近的 table,td,th,body元素。当元素的 style.display 设置为 "none" 时,offsetParent 返回 null。
offsetTop 和 offsetLeft 都是相对于其内边距边界的。
参考文献:offsetParent MDN
offset系列
offsetTop、offsetLeft
只读属性,它返回当前元素相对于其 offsetParent元素的顶部(左部)内边距的距离。
举个块级元素的栗子:
<div className='slide' ref={parentRef}>
<div id='child' ref={childRef}></div>
</div>
.slide {
width: 200px;
height: 500px;
overflow: scroll;
margin: 30px auto;
position:relative;
border: 1px solid #000;
}
#child {
width: 50px;
height: 700px;
margin: 30px auto;
/* padding-top: 100px; */
/* padding-left: 20px; */
/* box-sizing: border-box; */
background-color: aqua;
}

如图所示: 我们给child设置了margin:30px auto;所以child的offsetTop:30px,offsetLeft:75px [(200 - 50) / 2],offsetWidth = width(50px),offsetHeight(700px)
如果我们给child设置了padding就会有不同

如图所示:
我们给child设置了padding-top:100px;padding-left:20px;,padding-top没有影响offsetTop的值,但offsetHeight的值改变为800px(height + padding),padding-left使offsetWidth的值变成了70px,offsetLeft的值变成了65px[(200 - width50px - padding20px) / 2]
如果我们设置了box-sizing:border-box结果和第一种一样
总结:
- 需要注意child的offset属性之所以基于slide计算,是因为我们给slide设置了相对定位,child的offsetParent是slide
- padding会影响元素的offsetWidth=盒子的宽度=width+padding=70px,我们设置的宽度只是width的值,所以也会影响offsetLeft,padding会影响元素的offsetHeight,但是不会影响offsetTop
- 我们设置了box-sizing:border-box,盒子的宽度=padding+width=50px,我们设置的宽度就是width+padding,所以和情况1一致。
offsetWidth、offsetHeight
offsetWidth只读属性,返回一个元素的布局宽度。 offsetWidth = padding + border + width + scrollbar(竖直方向滚动条)
offsetHeight只读属性,返回一个元素的布局高度。 offsetHeight = padding + border + height + scrollbar (水平方向滚动条)
举个行内元素的栗子:
<div className='slide' ref={parentRef}>
<div id='child' ref={childRef}></div>
<div id='spanPartent'>
<span id={'inline-1'}>你好你好</span>
<span id={'inline-2'}>这是第二个span元素,这是第二个span元素</span>
</div>
</div>
.slide {
width: 200px;
height: 500px;
overflow: scroll;
margin: 30px auto;
position:relative;
border: 1px solid #000;
}
#child {
width: 50px;
height: 700px;
margin: 30px auto;
padding-top: 100px;
padding-left: 20px;
box-sizing: border-box;
background-color: aqua;
}
#spanPartent {
border: 1px solid green;
}
#inline-1 {
border: 1px solid blue;
margin-left: 30px;
}
#inline-2 {
border: 1px solid red;
margin-left: 20px;
padding-top: 20px;
}
31 'span-1offsetLeft'
117 'span-2offsetLeft'
760 'span-1offsetTop'
740 'span-2offsetTop'
66 'span-1offsetWidth'
197 'span-2offsetWidth'
25 'span-1offsetHeight'
90 'span-2offsetHeight'
如图所示:
我们可以直观的看出来span元素的计算方式,padding会影响span元素的高度,进而会影响offsetHeight和offsetTop的值。span1和span2的值也是不一样的。
client系列
clientTop 表示一个元素的上边框宽度,是只读属性。 clientLeft 表示一个元素的左边框的宽度,以像素表示。如果元素的文本方向是从右向左(RTL, right-to-left),并且由于内容溢出导致左边出现了一个垂直滚动条,则该属性包括滚动条的宽度。clientLeft 不包括左外边距和左内边距。clientLeft 是只读的。
- 简单来说是我们设置的border的宽度,但是如果你是用outline或者box-shadow设置的边框是不会计算在内。
- 行内元素是不存在client属性的,属性值都为0。
- clientWidth和clientHeight的值是padding+width/height的值不包括border,怪异盒模型和IE盒模型都如此。
#child {
width: 50px;
height: 700px;
margin: 30px auto;
padding-top: 100px;
padding-left: 20px;
box-sizing: border-box;
border: 5px solid red;
background-color: aqua;
}
5 'clientTop'
5 'clientLeft'
40 'clientWidth'
690 'clientHeight'
#child {
width: 50px;
height: 700px;
margin: 30px auto;
padding-top: 100px;
padding-left: 20px;
border: 5px solid red;
background-color: aqua;
}
0 'clientTop'
0 'clientLeft'
50 'clientWidth'
700 'clientHeight'
scroll系列
scrollTop 可设置的
scrollTop 值是这个元素的内容顶部(卷起来的)到它的视口可见内容(的顶部)的距离的度量。当一个元素的内容没有产生垂直方向的滚动条,那么它的 scrollTop 值为0,我们可以理解为滚动条顶部到其设置了overflow:scroll的父元素的边框位置的高度。
scrollWidth 这个只读属性是元素内容宽度的一种度量,包括由于 overflow 溢出而在屏幕上不可见的内容。计算规则和clientWidht相同,如果没有溢出滚动则值等同于clientWidth。
scrollTo
scrollTo是给设置了overflow;scroll的元素调用的方法,可以控制元素滚动到相应的位置
element.scrollTo(x-coord, y-coord)
element.scrollTo({ top: 100, left: 100, behavior: 'smooth' });
scrollIntoView
scrollIntoView MDN scrollIntoView是给设置了overflow;scroll元素的子元素调用的方法
<div className='slide' ref={parentRef}>
<div id='child' ref={childRef}></div>
</div>
.slide {
width: 200px;
height: 500px;
overflow: scroll;
margin: 30px auto;
position:relative;
border: 1px solid #000;
}
#child {
width: 50px;
height: 2000px;
margin: 30px auto;
background-color: aqua;
}
parentRef.current.scrollTo(0, 30)
childRef.current.scrollIntoView(true)
// 以上这两种方法等同
scrollBy
滚动的位置是相对的,也就是说第一次滚动到(100, 100)的位置第二次再滚动就是以(100,100)为起点滚动,就会到(200,200)的位置 与scrollTo不同,scrollTo每次都是绝对位置,每次都是从(0,0)开始计算的。