平滑滚动到顶部或底部的几种方案

9,271 阅读3分钟

开始

最近项目在做列表展示相关的需求,要求有滚动到顶部和底部的快捷按钮,在参考过社区的一些文章后,写下这篇文章,供大家参考!

很多时候我们使用的滚动效果都是类似于锚点那种,一闪而过,给人的体验十分不友好。所以这里介绍一些平滑滚动的方式。

里面有一些相关的知识点,不了解的可以参考这篇文章:链接地址

首发地址

使用CSS的scroll-behavior

scroll-behavior: auto | smooth | inherit | unset

一般我们使用auto和smooth就可以了,smooth表示滚动很平滑,有过渡效果,auto没有过渡效果,一闪而过。

我们一般回到顶部的话把这个属性设置在html上即可。代码如下

<div id="container" class="box">
  <p>Hello, Backtotop</p>
  <br/>
  <p>Hello, Backtotop</p>
  <br/>
  <p>Hello, Backtotop</p>
  <br/>
  <p>Hello, Backtotop</p>
  <br/>
  /* 省略部分代码 */
</div>
<a href="#container" class="backto-top-btn">回到顶部按钮</a>

css样式代码:

html {
  scroll-behavior: smooth;
}

注意:上面那个我用的a标检加id,这种可能不太好,因为a标签的默认行为会给地址加一个hash,这对vue的路由使用hash模式来说会出现问题。

更简单的方法

  • 回到顶部 上面a标签的默认行为会出问题,我们可以使用更简便的方式来实现,首先在你的页面的给html加一个样式:
html {
  scroll-behavior: smooth;
}

给你的回到顶部的按钮绑定一个事件,比如点击事件,里面加入我们平时使用的回到顶部的代码

window.scrollTo(0, 0);

然后这样的话,只要你的设备及浏览器支持这个CSS属性的话,那么也会有过渡平滑的效果。

  • 回到底部 回到底部可以这样操作,我们计算出DOM元素的高度,减去我们视窗的高度,那么就是底部了
window.scrollTo(0, document.documentElement.scrollHeight - window.innerHeight);

手头设备支持情况

  • iOS 13.3 Safari 不支持smooth
  • iOS 11.4.1 Safari 不支持smooth
  • Galaxy S9 Android 9.0 自带浏览器 支持smooth
  • Chrome 79 支持smooth

使用JS的Element.scrollIntoView()

element.scrollIntoView(); // 等同于element.scrollIntoView(true) 
element.scrollIntoView(alignToTop); // Boolean型参数 
element.scrollIntoView(scrollIntoViewOptions); // Object型参数

这个是浏览器自带的滚动函数,目前也是属于新功能,可能很多设备及浏览器不支持。这里贴一张MDN的参数解释

这个感觉用起来比CSS还要简单些,给你要滚动的DOM元素绑定这个函数即可

// 滚动到顶部
this.$refs.container.scrollIntoView(true); // vue的语法

// 滚动到底部
this.$refs.container.scrollIntoView(false);  // vue的语法

手头设备支持情况

  • iOS 13.3 Safari 不支持smooth
  • iOS 11.4.1 Safari 不支持smooth
  • Galaxy S9 Android 9.0 自带浏览器 支持smooth
  • Chrome 79 支持smooth

多设备支持的缓冲方案

// 封装一个回到底部或者顶部的函数
scrollToTop(position) {
  // 使用requestAnimationFrame,如果没有则使用setTimeOut
  if(!window.requestAnimationFrame) {
    window.requestAnimationFrame = function(callback) {
      return setTimeout(callback, 20)
    }
  }

  // 获取当前元素滚动的距离
  let scrollTopDistance = document.documentElement.scrollTop || document.body.scrollTop;

  function smoothScroll() {
    // 如果你要滚到顶部,那么position传过来的就是0,下面这个distance肯定就是负值。
    let distance = position - scrollTopDistance;
    // 每次滚动的距离要不一样,制造一个缓冲效果
    scrollTopDistance = scrollTopDistance + distance / 5;
    // 判断条件
    if(Math.abs(distance) < 1) {
      window.scrollTo(0, position);
    }else {
      window.scrollTo(0, scrollTopDistance);
      requestAnimationFrame(smoothScroll);
    }
  }

  smoothScroll();
 }

调用这个函数

// 回到顶部
scrollToTop(0);

// 滚到底部
scrollToTop(document.documentElement.scrollHeight - window.innerHeight);

这里给出一下效果展示

手头设备支持情况

  • iOS 13.3 Safari 支持
  • iOS 11.4.1 Safari 支持
  • Galaxy S9 Android 9.0 自带浏览器 支持
  • Chrome 79 支持

参考资料

链接地址

感谢上面这位大佬的文章!