用 TOC 点击跳转案例学习滚动事件

用 'scroll'
定义滚动事件。
关于滚动事件
监听页面滚动
虽然可以监听任何一个元素的滚动,但是通常情况会监听整个页面的滚动。这时候我们对 window
添加监听器就行了。
1 | window.addEventListener('scroll', function () { |
获取已滚动的值
通常情况下,我们需要获取 HTML 中已经滚动的值:
元素.scrollTop
用于具有滚动条的元素节点,且可读写window.scrollY
仅仅用于页面,且只读,不可重新赋值
获取 HTML 元素的固定写法:
1 | const html = document.documentElement; |
获取 body 元素的固定写法:
1 | const body = document.body; |
在现代浏览器中,通常都是获取 HTML 的滚动值。然而为了兼容 IE,可以这样写:
1 | // 当前页面的垂直滚动位置 |
下面这个例子,仅仅当已经滚动 100 像素的时候,才会显示盒子:
1 | const div = document.querySelector('div') |
操作页面滚动
用手拉进度条
真 · 有手就行
- 给
window.scrollY
赋值
由于 元素.scrollTop
或者 window.scrollY
取得的值是可读写的,用 JS 操作这个值可以改变元素已滚动的距离(这里的元素通常指 HTML)
window.scrollTo(x, y)
操作页面滚动到某个地方,第一个值通常取 0 ,因为没人喜欢横着滚。
Element.scrollIntoView();
由需要被显示的子元素调用,
这会直接把父容器滚动到该元素的位置。这在制作点击跳转到某个元素的时候会很有用。
括号里可以传入一个对象,比如下面这段代码:
1 | expectLife.scrollIntoView({ behavior: 'smooth', block: 'start' }); |
就会让 expectLife
的父元素滚动到 expectLife
所处的位置,并且以平滑的方式。block: 'start'
决定了元素的顶端将和其所在滚动区的可视区域的顶端对齐。
这其实有点像先获取元素在页面中的位置,再次操作页面滚动到这个位置:
1 | const n = item.offsetTop; |
关于滚动值的单位
获取到的 document.documentElement.scrollTop
是不带单位的,虽然它的单位就是 px
。
我一直好奇这种情况下,怎么实现响应式网页设计?其实思路很简单:
用页面内容高度 document.documentElement.scrollHeight
减去一屏的视口高度(因为首屏不需要滚的时候就能看到) document.documentElement.clientHeight
,就能得到可滚动的总距离。然后用已经滚动的距离除一下,就能获得已滚动的占比了:
1 | // 已滚动距离 |
clientHeight
和 offsetHeight
区别?两者都是用来获取元素的尺寸,计算时候都不包含 margin ,都包含 padding,区别在于 clientHeight 不含 border。
平滑滚动
有时候想让页面滚动有动画,而不是直接跳过去。
CSS
1 | html { |
遗憾的是,似乎操作不了更多行为。
js
函数调用时候加上平滑
可以使用带参数对象的函数调用,同样加上平滑属性。
1 | window.scrollTo({ |
使用外部库
考虑使用专业的滚动动画库,如:
- GSAP (GreenSock Animation Platform): 提供精细控制的滚动动画
- ScrollMagic: 专门用于滚动交互
- Lenis: 专注于平滑滚动的轻量库
其他
除此之外,还可以通过 Window.scrollTo()
方法配合 ScrollToOptions
对象实现效果。太复杂,就不写了。
制作 TOC 的几种方式
纯 HTML
HTML 自带一个锚点机制:
URL#item-1
可以跳转到页面中 id="item-1"
的元素。
所以我们只需要这样做:
1 | <nav> |
然后给被点击的按钮加个超链接就行了。
JS 的 scrollIntoView()
方法
1 | btn.addEventListener("click", function () { |
先计算距离,再跳过去
上面已经说过了,就不解释了
1 | btn.addEventListener("click", function () { |
- 标题: 用 TOC 点击跳转案例学习滚动事件
- 作者: 三葉Leaves
- 创建于 : 2025-05-21 00:00:00
- 更新于 : 2025-06-07 19:46:13
- 链接: https://blog.oksanye.com/f9e94a3b6584/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。