最近项目需要做一个H5页面的问答类互动,类似向上向下的滚动效果,所以做个总结
一、 CSS
使用CSS的scroll-behavior,可以达到比较平滑的滚动,有过渡效果
scroll-behavior: auto | smooth | inherit | unset
// html
<div id="box">
<p id="container">Hello, Backtotop</p>
<br/>
<p>Hello, Backtotop</p>
<br/>
<p>Hello, Backtotop</p>
<br/>
<p>Hello, Backtotop</p>
<br/>
</div>
<a href="#container" >回到顶部按钮</a>
// css
#box {
height: 150px;
overflow: scroll;
scroll-behavior: smooth;
}
这种方法虽然可以平滑滚动到顶部,但是因为a标签的默认行为会给地址加一个hash,这对路由使用hash模式来说会出现问题。
二、ScrollTo
回到顶部
target.clientHeight
// html
<div id="box">
<p id="container">Hello, Backtotop</p>
<br/>
<p>Hello, Backtotop</p>
<br/>
<p>Hello, Backtotop</p>
<br/>
<p>Hello, Backtotop</p>
<br/>
</div>
<a onclick="up()" href="#">回到顶部按钮</a>
// css
#box {
height: 150px;
overflow: scroll;
scroll-behavior: smooth;
}
// js
function up() {
const target = document.getElementById("box");
target.scrollTo(0, 0);
}
回到底部
DOM元素的高度,减去我们视窗的高度,就是底部了
window.scrollTo(0, document.documentElement.scrollHeight - window.innerHeight);
function down() {
const target = document.getElementById("box");
target.scrollTo(0, target.scrollHeight - target.clientHeight);
}
设备支持情况
- iOS 13.3 Safari 不支持smooth
- iOS 11.4.1 Safari 不支持smooth
- Galaxy S9 Android 9.0 自带浏览器 支持smooth
- Chrome 79 支持smooth
三、ScrollIntoView
element.scrollIntoView(); // 等同于element.scrollIntoView(true)
element.scrollIntoView(alignToTop); // Boolean型参数
element.scrollIntoView(scrollIntoViewOptions); // Object型参数
// html
<div id="box">
<p id="top">Hello, Backtotop</p>
<br/>
<p>Hello, Backtotop1</p>
<br/>
<p>Hello, Backtotop2</p>
<br/>
<p>Hello, Backtotop3</p>
<br/>
<p>Hello, Backtotop4</p>
<br/>
<p id="bottom">Hello, Backtotop5</p>
<br/>
</div>
<a onclick="up()" href="#">回到顶部按钮</a>
<a onclick="down()" href="#">回到底部按钮</a>
function up() {
const target = document.getElementById("top");
target.scrollIntoView(false);
}
function down() {
const target = document.getElementById("bottom");
target.scrollIntoView(true);
}
设备支持情况
- iOS 13.3 Safari 不支持smooth
- iOS 11.4.1 Safari 不支持smooth
- Galaxy S9 Android 9.0 自带浏览器 支持smooth
- Chrome 79 支持smooth
四、多设备支持的滚动
以上的方法,安卓大部分都是可用的,IOS虽然也是可以滚动,但是却不支持options,所以无法缓慢滚动,都是一下子滚到底,所以为了让安卓和IOS都能够缓慢滚动,需要有一个兼容性的滚动方案
function scrollTopSmooth(position, sumTime = 45, target) {
// 不存在原生`requestAnimationFrame`,用`setTimeout`模拟替代
if (!window.requestAnimationFrame) {
window.requestAnimationFrame = function(cb) {
return setTimeout(cb, 20)
}
}
// 当前滚动高度
let scrollTop = target
? target.scrollTop
: document.documentElement.scrollTop || document.body.scrollTop
// 当前滚动对象
let scrollTarget = target || window
// sumTime 控制滚动速率, scrollTime做判断
let scrollTime = sumTime
// step
function step() {
let distance = position - scrollTop
scrollTime--
scrollTop = scrollTop + distance / sumTime
if (!scrollTime) {
scrollTarget.scrollTo(0, position)
} else {
scrollTarget.scrollTo(0, scrollTop)
requestAnimationFrame(step)
}
}
step()
}
补充
-
document.documentElement.scrollTop与document.body.scrollTop
document.documentElement表示获取到html,document.body表示获取到body。使用document.body.scrollTop获取不到页面滚动的距离,就必须使用document.documentElement.scrollTop来获取。所以一般我们获取滚动距离的兼容代码最好写成这样
let scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
-
关于绑定滚动事件scroll
只有window和document两个能绑定scroll滚动事件,document.documentElement和document.body绑定不起,这个应该跟浏览器内核有关系。
设备支持情况
- iOS 13.3 Safari 支持
- iOS 11.4.1 Safari 支持
- Galaxy S9 Android 9.0 自带浏览器 支持
- Chrome 79 支持