当页面上有很多内容时需要一个返回页面顶部的按钮使用户可以快速返回页面顶部。让我们看一下可以做到返回页面顶部的几种方法,从简单开始,然后逐步改进。
保持简单
<style>
#scrollToTopBtn {
background-color: black;
border: none;
border-radius: 50%;
color: white;
cursor: pointer;
font-size: 16px;
line-height: 48px;
width: 48px;
}
</style>
<footer>
<!-- Scroll to top button -->
<button id="scrollToTopBtn">☝️</button>
</footer>
<script>
var scrollToTopBtn = document.getElementById("scrollToTopBtn");
var rootElement = document.documentElement;
function scrollToTop() {
// Scroll to top logic
rootElement.scrollTo({
top: 0,
behavior: "smooth"
})
}
scrollToTopBtn.addEventListener("click", scrollToTop);
</script>
检测滚动位置
scrollHeight:给出元素的高度,包括溢出而不可见的部分。
clientHeight:给出元素的内部高度(以像素为单位),即可见部分的高度。
scrollHeight减去clientHeight得到可以滚动的总像素,通过rootElement.scrollTop滚动量除以我们可以滚动的总像素,可以得到0到1之间的比例。
当用户向下滚动页面总高度80%(或0.80的比例)时,显示滚动至顶部按钮。80%是任意数字。基本上,我们越接近1,用户在看到按钮之前必须滚动越多。
<style>
.scrollToTopBtn {
/* same general styles as before */
/* place it at the bottom-right corner */
position: fixed;
bottom: 30px;
right: 30px;
/* keep it at the top of everything else */
z-index: 100;
/* hide with opacity */
opacity: 0;
/* also add a translate effect */
transform: translateY(100px);
/* and a transition */
transition: all .5s ease
}
.showBtn {
opacity: 1;
transform: translateY(0)
}
</style>
<script>
var scrollToTopBtn = document.getElementById("scrollToTopBtn");
var rootElement = document.documentElement;
function handleScroll() {
// Do something on scroll
var scrollTotal = rootElement.scrollHeight - rootElement.clientHeight
if ((rootElement.scrollTop / scrollTotal ) > 0.80 ) {
// Show button
scrollToTopBtn.classList.add("showBtn")
} else {
// Hide button
scrollToTopBtn.classList.remove("showBtn")
}
}
document.addEventListener("scroll", handleScroll);
</script>
设置滚动事件监听性能开销可能会很高.....
Intersection Observer
Intersection Observer API是解决上述问题的绝佳解决方案。这是一个相当新的浏览器API,使开发人员可以以更优化的方式将大多数任务交给浏览器处理。
var target = document.querySelector("footer");
function callback(entries, observer) {
// The callback will return an array of entries, even if you are only observing a single item
entries.forEach(entry => {
if (entry.isIntersecting) {
// Show button
scrollToTopBtn.classList.add('showBtn')
} else {
// Hide button
scrollToTopBtn.classList.remove('showBtn')
}
});
}
let observer = new IntersectionObserver(callback);
observer.observe(target);
平滑滚动又如何实现呢?
<html id="top">
<body>
<!-- the entire document -->
<a href="#top">Jump to top of page</a>
</body>
</html>
html {
scroll-behavior: smooth;
}