如何制作一个不显眼的滚动到顶部按钮

Avatar of Marcel Rojas
Marcel Rojas

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 价值 200 美元的免费积分!

返回页面顶部的按钮可以让用户快速返回页面顶部,而无需花费太多精力。当页面包含大量内容或在单页网站上使用无限滚动时,这非常有用,或者在移动设备上,不同的屏幕尺寸会导致内容滚动扩展。

这些按钮通常浮动在网站的底部角落,然后在点击时将您带回页面顶部。使用 JavaScript 创建它们非常容易。但在视觉上,我们希望它不显眼,同时又足够大,以便于点击或轻触。让我们看看几种实现方法,从简单开始,然后逐步改进。

选项 1:保持简单

首先,我们在 JavaScript 中选择按钮。

var scrollToTopBtn = document.getElementById("scrollToTopBtn")

现在,document.documentElement 返回文档的根元素。我们需要它来获取偏移值。因此,接下来我们将其保存在名为 rootElement 的变量中,这样在代码中更容易调用。

var rootElement = document.documentElement

我们将在按钮上添加一个点击事件监听器

function scrollToTop {
  // scroll to top logic
}

scrollToTopBtn.addEventListener("click", scrollToTop)

然后,在 scrollToTop 函数中,我们将使用 scrollTo 方法使其滚动到屏幕顶部。

function scrollToTop() {
  // Scroll to top logic
  rootElement.scrollTo({
    top: 0,
    behavior: "smooth"
  })
}

我们也可以稍微调整按钮的样式

#scrollToTopBtn {
  background-color: black;
  border: none;
  border-radius: 50%;
  color: white;
  cursor: pointer;
  font-size: 16px;
  line-height: 48px;
  width: 48px;
}

现在我们可以将按钮放置在页面的某个位置,例如页脚

<footer>
  <!-- Scroll to top button -->
  <button id="scrollToTopBtn">☝️</button>
</footer>

我们得到的结果如下

选项 2:检测滚动位置

我们可以使用滚动事件监听器检测滚动。

function handleScroll() {
  // Do something on scroll
}
document.addEventListener("scroll", handleScroll)

handleScroll 函数将在用户每次滚动时被调用。现在我们需要我们能够滚动的像素总数。

  • scrollHeight 给出元素的高度,包括由于溢出而不可见的部分。
  • clientHeight 给出元素的内部高度(以像素为单位),即可见部分的高度。

如果我们将 scrollHeight 减去 clientHeight,我们就可以得到可以垂直滚动的像素总数。

var scrollTotal = rootElement.scrollHeight - rootElement.clientHeight

现在我们有一个名为 scrollTotal 的变量,它表示可以垂直滚动的最大像素数。通过将已滚动量除以可以滚动的像素总数,我们得到 0 到 1 之间的比率。使用此比率,我们可以轻松地打开和关闭按钮。

例如,我们将添加一个条件,当用户滚动到页面总高度的 80%(或比率为 0.80)时显示滚动到顶部按钮。80% 是一个任意数字。基本上,越接近 1,用户需要滚动更多才能看到按钮。

以下是 JavaScript 代码

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)

我们需要一些 CSS 代码来在按钮进入视野时将其正确定位

.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)
}

有了它,当用户滚动到页面 80% 的位置时按钮就会出现,当滚动到更高位置时按钮就会隐藏。

这似乎是一个不错的选项,设置一个事件监听器来执行此操作非常容易。但由于我们一直在检查当前滚动位置,因此性能开销可能会很大。

还有另一个选项可以解决这个问题……

选项 3:交叉观察器

交叉观察器 API 是解决上述问题的绝佳方案。它是一个相当新的浏览器 API,它允许开发人员将大多数这些任务委托给浏览器,从而实现更优化的性能。Travis Almand 撰写了关于其工作原理的 详细说明。以下是 MDN 的定义

交叉观察器 API 提供了一种异步方式来观察目标元素与祖先元素或顶级文档视窗交叉部分的变化。

非常棒!这意味着按钮可以作为我们的目标元素

// We select the element we want to target
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')
    }
  });
}

我们需要创建一个新的 IntersectionObserver 实例,并将刚刚编写的回调函数传递给它。

let observer = new IntersectionObserver(callback);

最后,我们告诉观察器开始观察上面选择的目标元素,以便在它与视窗交叉时进行处理

observer.observe(target);

那么平滑滚动呢?

当然可以!事实上,Chris 在 2019 年就向我们展示了如何使用 CSS 实现平滑滚动

<html id="top">
  <body>
     <!-- the entire document -->
     <a href="#top">Jump to top of page</a>
  </body>
</html>
html {
  scroll-behavior: smooth;
}

这里有一些细微差别,例如 Chris 在文章中也介绍的可访问性增强。重点是,CSS 正在获得新的功能,可以完成我们以前使用 JavaScript 来完成的任务。


就是这样!我们从一个非常简单的想法开始。我们通过根据用户的滚动位置显示和隐藏按钮来对其进行了改进。然后,我们通过实现交叉观察器 API 来改进性能,而不是监视当前滚动位置。最后,我们看到了如何使用 CSS 实现平滑滚动。总而言之,我们得到一个滚动到顶部按钮,它易于查看和使用,同时不会阻塞页面上的其他元素。