由于scroll中会涉及到元素的尺寸和位置的计算,这里先借助网上的一张图来回顾一下。
图片来源自: 使用 CSSOM 测量元素尺寸和位置 。
需要注意的是:
clientHeight = 内容高度+上下padding-滚动条的粗度。
对于同一个元素来说,盒模型会影响clientHeight的值。
clientHeight返回的是整数。
#scroll-container2 {
margin: 100px 0px 70px 50px;
border: 7px solid black;
box-sizing: border-box; // box-sizing的值会影响clientHeight、clientWidth的值
height: 200.22px;
width: 300.22px;
padding: 10px;
overflow: auto;
}
// 备注:该示例里没有水平滚动条
getClientWidth() {
/**
* (1)对于content-box,CSS height属性只包含内容的高度,不包含padding和border。
* 内容高度contentHeight = 200.22
* clientHeight = CSS height + CSS 上下padding = 200.22+10+10=220.22 clientHeight会返回整数 220
*
* (2)对于border-box,CSS height属性包含了内容的高度,padding和border。
* 内容高度contentHeight = 200.22(CSS height)-7(上border)-7(下border)-10(上padding)-10(下padding)=166.22。
* clientHeight = 内容height+上下padding = 166.22+10+10=186.22 clientHeight会返回整数 186
*/
const scrollContainer = document.getElementById('scroll-container2')!;
console.log('clientHeight', scrollContainer?.clientHeight);
}
overflow: scroll
或 overflow: auto
,并且它包含的内容溢出了其有限的可视区时,就会显示滚动条,内容可滚动。一些无关紧要的示例代码:
<div style="display: flex">
<div id="scroll-container1">内容很少,没有滚动条div>
<div id="scroll-container2">
01. 内容很多,有滚动条<br />
02. 内容很多,有滚动条<br />
03. 内容很多,有滚动条<br />
04. 内容很多,有滚动条<br />
05. 内容很多,有滚动条<br />
06. 内容很多,有滚动条<br />
07. 内容很多,有滚动条<br />
08. 内容很多,有滚动条<br />
09. 内容很多,有滚动条<br />
10. 内容很多,有滚动条<br />
11. 内容很多,有滚动条<br />
12. 内容很多,有滚动条<br />
13. 内容很多,有滚动条<br />
14. 内容很多,有滚动条<br />
15. 内容很多,有滚动条<br />
<div id="target">test scrollIntoView()div>
01. 内容很多,有滚动条<br />
02. 内容很多,有滚动条<br />
03. 内容很多,有滚动条<br />
04. 内容很多,有滚动条<br />
05. 内容很多,有滚动条<br />
06. 内容很多,有滚动条<br />
07. 内容很多,有滚动条<br />
08. 内容很多,有滚动条<br />
09. 内容很多,有滚动条<br />
10. 内容很多,有滚动条<br />
11. 内容很多,有滚动条<br />
12. 内容很多,有滚动条<br />
13. 内容很多,有滚动条<br />
14. 内容很多,有滚动条<br />
15. 内容很多,有滚动条<br />
div>
div>
#scroll-container1,
#scroll-container2 {
margin: 100px 0px 70px 50px;
border: 7px solid black;
box-sizing: border-box; // content-box
height: 200.22px;
width: 300.22px;
padding: 10px;
overflow: scroll; // auto
}
#target {
height: 50px;
padding: 10px;
background-color: bisque;
border: 1px solid black;
}
当用户滚动某个元素的内容时 scroll 事件将会被触发。
由于 scroll 事件可被高频触发,容易造成高性能的消耗。推荐使用 requestAnimationFrame()
、 setTimeout()
或 CustomEvent
给事件节流,比如:
const scrollContainer = document.getElementById('scroll-container')!;
scrollContainer.addEventListener('scroll', () => {
requestAnimationFrame(() => {
// do something here
console.log('我滚动啦');
});
});
显示器有固定的刷新频率,每秒最多只能重绘60次或75次,即60Hz或75Hz。requestAnimationFrame 充分利用显示器的刷新机制,与这个刷新频率保持同步,来进行页面重绘,从而节省系统资源,提高系统性能,改善视觉效果。
element.scroll(x-coord, y-coord)
:让滚动条滚动到指定容器的某个坐标。
element.scroll(options)
:让滚动条滚动到指定容器的某个坐标,且可以指定滚动行为。
element.scrollTo() 同 element.scroll()。
const scrollContainer = document.getElementById('scroll-container')!;
// 1. 内容垂直方向向上滚动50px
scrollContainer.scroll(0, 50);
// 2. 内容垂直方向向上滚动50px
scrollContainer?.scroll({
top: 50,
left: 0,
behavior: 'smooth', // 指定滚动行为,支持参数 smooth(平滑滚动),默认值auto(瞬间滚动)
});
scroll、scrollTo、scrollBy 接收参数一样。区别:
scroll 和 scrollTo 用法基本一致。
scrollTo
滚动的距离是 绝对
的,就是不管执行多少次,滚动的位置都是一样的。
scrollBy
滚动的距离是 相对
的,每执行一次就会在原来的滚动基础上加上相对的距离。
滚动element的父容器,使element对用户可见。
element.scrollIntoView(alignToTop)
:alignToTop可选。