浏览器太低级了

守口如瓶,笑脸相迎。叩首问路,码梦为生。 --Vace

smooth-scroll 兼容处理方案

2021/03/21    前端


问题场景

想使用原生的滚动功能,并支持锚点的跳转方式,发现safair/IE/Edge等不支持smooth。

MDN文档

当用户手动导航或者 CSSOM scrolling API 触发滚动操作时,CSS 属性 scroll-behavior 为一个滚动框指定滚动行为,其他任何的滚动,例如那些由于用户行为而产生的滚动,不受这个属性的影响。在根元素中指定这个属性时,它反而适用于视窗。

  • auto 滚动框立即滚动。
  • smooth 滚动框通过一个用户代理预定义的时长、使用预定义的时间函数,来实现平稳的滚动,用户代理应遵循其平台的约定,如果有的话。

JS兼容解决方案(smoothscroll)

借助smoothscroll.jspolyfill可以让浏览器支持scroll-behavior。其原理是通过覆盖滚动元素的scrollscrollTo的事件来处理的。

在浏览器环境中,会自动运行补丁。

<script src="https://unpkg.com/smoothscroll"></script>

现在就可以通过JS来使用smooth滚动了

window.scroll({ top: 2500, left: 0, behavior: 'smooth' });
window.scrollBy({ top: 100, left: 0, behavior: 'smooth' });
window.scrollBy({ top: -100, left: 0, behavior: 'smooth' });
document.querySelector('.hello').scrollIntoView({ behavior: 'smooth' });

// scrollTo
element.scroll({ top: 0, left: 0, behavior: 'smooth' });
// Scroll to top
window.scroll({ top: 0, left: 0, behavior: 'smooth' });
document.querySelector('header').scrollIntoView({ behavior: 'smooth' });

支持anchor的兼容解决方案

使用smoothscroll基本已经够用了,但是如果页面有锚点的话,比如<a href="#hello">GO</a>,还是无法生效,本来打算写一个插件,通过监听hashchange拦截,并使用js平滑滚动到锚点,一番查询发现已经有这个轮子了smoothscroll-anchor-polyfill,原理也是差不多的,足够用了。

  1. 使用css定义
html {
    /* CSS custom property for the polyfill */
    --scroll-behavior: smooth;
    /* Normal CSS property for browsers with native support */
    scroll-behavior: smooth;
}

或者内联标签<html style="scroll-behavior: smooth;">...

  1. 加载polyfill,可以使用npm
<!--html-->
<script src="https://unpkg.com/smoothscroll-anchor-polyfill"></script>

// js
// Import any polyfill to enable smoothscroll for JS APIs
import smoothscrollPolyfill from 'smoothscroll-polyfill';

// Import this package to apply the smoothscroll to anchor links
import smoothscrollAnchorPolyfill from 'smoothscroll-anchor-polyfill';

// (Unlike this package, smoothscroll-polyfill needs to be actively invoked: )
smoothscrollPolyfill.polyfill();

注1:经过我的测试,好像不支持转义了的中文锚点,最好用en命名! 注2:此插件的实现原理是调用window.scroll()Element.scrollIntoView()实现的(如果这两个方法不吃smooth,那么这个也是不行的),所以如果插件未生效,先得检查一下,可以引入smoothscroll.js

参考链接

评论加载中...