首页 > 解决方案 > 如何在 Safari 上平滑滚动到(或等效)?

问题描述

我有一个简单的应用程序,我需要平滑滚动到某个页面。

这在 Chrome 上运行良好,但在 Safari 上,当我需要平滑滚动过渡时,我会突然跳回顶部。

根据 MDN 文档scrollTowith 选项确实不适用于 Safari。既然是这种情况,我怎么能得到这种等效的效果呢?

这是我目前使用的一个简单.scrollTo([options])调用的示例应用程序。

const App = () => {
  const scrollUp = () => {
    const scroll = document.getElementsByClassName("wrapper");
    scroll[0].scrollTo({
      top: 0,
      behavior: "smooth"
    });
  };

  return (
  <div className = "wrapper"
    style = {
      {
        height: 300,
        overflowY: "scroll"
      }
    }>
    <h1> Scroll all the way down to see the scroll up button </h1>
    <p>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua.Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. </p>
    <p>
    Dui id ornare arcu odio ut.Tempus iaculis urna id volutpat lacus laoreet non curabitur.Nullam vehicula ipsum a arcu cursus vitae congue mauris.Etiam tempor orci eu lobortis elementum nibh tellus molestie.Et malesuada fames ac turpis egestas.Placerat vestibulum lectus mauris ultrices eros.Pharetra magna ac placerat vestibulum.Facilisis volutpat est velit egestas dui id ornare arcu odio.Consequat id porta nibh venenatis cras sed felis.Tincidunt lobortis feugiat vivamus at augue eget arcu dictum.Turpis egestas sed tempus urna et pharetra.Quis imperdiet massa tincidunt nunc.Faucibus vitae aliquet nec ullamcorper sit amet risus nullam eget. </p>
    <p>
    Tellus at urna condimentum mattis.Massa sapien faucibus et molestie ac feugiat sed lectus.Et molestie ac feugiat sed lectus vestibulum mattis ullamcorper velit.Ac odio tempor orci dapibus.Enim nulla aliquet porttitor lacus luctus accumsan tortor.Vitae proin sagittis nisl rhoncus mattis rhoncus.Mi proin sed libero enim.Cursus eget nunc scelerisque viverra.Id diam vel quam elementum.Nulla aliquet enim tortor at.Morbi tincidunt ornare massa eget egestas purus viverra accumsan.Suscipit tellus mauris a diam maecenas.Purus sit amet luctus venenatis lectus magna fringilla.Aliquet bibendum enim facilisis gravida neque convallis. </p>
    <p>
    Vel eros donec ac odio tempor orci.In aliquam sem fringilla ut morbi tincidunt augue interdum.Placerat duis ultricies lacus sed turpis tincidunt id aliquet risus.Ac orci phasellus egestas tellus rutrum tellus.In metus vulputate eu scelerisque felis imperdiet proin fermentum leo.Duis at tellus at urna condimentum.Enim diam vulputate ut pharetra sit amet aliquam.Lectus quam id leo in vitae.Elementum sagittis vitae et leo duis ut diam quam.Blandit aliquam etiam erat velit scelerisque in dictum non.Interdum velit laoreet id donec ultrices tincidunt arcu non sodales.Pulvinar proin gravida hendrerit lectus.Mauris cursus mattis molestie a iaculis at.Accumsan in nisl nisi scelerisque eu ultrices vitae auctor.Montes nascetur ridiculus mus mauris vitae.Amet nulla facilisi morbi tempus iaculis urna id volutpat. </p>
    <p>
    In nisl nisi scelerisque eu.Elit ut aliquam purus sit amet luctus.Et ultrices neque ornare aenean euismod elementum.A condimentum vitae sapien pellentesque habitant morbi.Neque viverra justo nec ultrices dui.Cras pulvinar mattis nunc sed blandit.Nunc sed augue lacus viverra vitae congue eu consequat ac.Pharetra vel turpis nunc eget lorem dolor sed.Etiam tempor orci eu lobortis elementum nibh tellus molestie nunc.Tincidunt augue interdum velit euismod in pellentesque massa. </p>

    <p>
    Vitae congue eu consequat ac felis donec et odio pellentesque.Nunc non blandit massa enim nec.Enim neque volutpat ac tincidunt.Elementum integer enim neque volutpat.Amet venenatis urna cursus eget nunc scelerisque viverra.Sollicitudin tempor id eu nisl nunc mi ipsum faucibus.Orci a scelerisque purus semper eget duis at tellus.Integer eget aliquet nibh praesent tristique magna sit.Congue quisque egestas diam in arcu cursus euismod quis.Justo donec enim diam vulputate ut pharetra sit amet aliquam.Aliquam ut porttitor leo a.Libero volutpat sed cras ornare arcu. </p>

    <p>
    Quis eleifend quam adipiscing vitae proin sagittis nisl rhoncus.Imperdiet massa tincidunt nunc pulvinar sapien.Volutpat sed cras ornare arcu dui vivamus arcu.Scelerisque purus semper eget duis at tellus at urna condimentum.Praesent semper feugiat nibh sed pulvinar proin gravida hendrerit.Sit amet consectetur adipiscing elit.Sit amet porttitor eget dolor morbi.Morbi enim nunc faucibus a pellentesque sit amet porttitor eget.Et netus et malesuada fames ac turpis egestas integer.Tristique senectus et netus et.Placerat in egestas erat imperdiet sed euismod.Tortor at risus viverra adipiscing at in tellus integer feugiat.Nibh mauris cursus mattis molestie a iaculis at.Enim ut sem viverra aliquet eget sit amet tellus.Lectus urna duis convallis convallis tellus id interdum velit laoreet.Ornare quam viverra orci sagittis eu volutpat odio.Eget gravida cum sociis natoque penatibus. </p>

    <p>
    Enim lobortis scelerisque fermentum dui faucibus in ornare quam viverra.Amet mauris commodo quis imperdiet massa tincidunt nunc pulvinar.Magna ac placerat vestibulum lectus mauris ultrices eros.Sed sed risus pretium quam vulputate.Arcu risus quis varius quam quisque id diam vel quam.Nunc vel risus commodo viverra maecenas accumsan lacus vel facilisis.Suspendisse faucibus interdum posuere lorem.Massa vitae tortor condimentum lacinia quis.Maecenas ultricies mi eget mauris pharetra.Praesent tristique magna sit amet.Lacus sed turpis tincidunt id aliquet risus.Ullamcorper dignissim cras tincidunt lobortis feugiat vivamus at.Neque convallis a cras semper auctor neque vitae tempus quam. </p>
    
    <button onClick={() => scrollUp()}> Scroll up </button>
</div>
  );
}


ReactDOM.render(<App/> ,
  document.getElementById('app')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
<div id="app"></div>

标签: javascripthtmlcssreactjs

解决方案


如果您想在所有浏览器(包括 IE 9 及更高版本和 Safari)中使用 JavaScript 函数 scroll、scrollTo 或 scrollBy 平滑(或动画)滚动到页面上的某个位置,并且您没有加载 jQuery,那么iamdustan smoothscroll polyfill可能是添加功能的最简单方法。

您可以将 polyfill 包含在页面的 head 部分并将其提供给每个用户(gzip 压缩时只有大约 1,400 字节),或者您可以进行测试,如果需要 polyfill,请将其添加到页面中。

Smoothscroll polyfill 可从 jsdelivr.net CDN 获得。

对于 IE9,还需要 requestAnimationFrame 的 polyfill 来处理动画。由于 IE9 用户越来越少,使用 IE 条件从您自己的服务器加载 polyfill 可能更容易。

如果用户在 Internet Explorer 上设置了首选减少运动的系统设置,则我包含了一些用于auto代替smooth滚动的代码,prefers-reduced-motion: reduce.’ I do ignore 因为 IE11 报告它在打开时已关闭(但 IE9,对 window.matchMedia 使用了 polyfill ,正确地报告了它)。我的假设是任何需要可访问性设置的人都将使用较新的浏览器之一。

var reducedMotionQuery = false;
var scrollBehavior = "smooth";
var one = document.querySelector("#one").offsetTop;
var two = document.querySelector("#two").offsetTop;
var three = document.querySelector("#three").offsetTop;

// If IE, just scroll - my assumption is an IE user won't be using reduced-motion
if (!(document.documentMode)) {
    if (typeof window.matchMedia === "function") {
        reducedMotionQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
    }

    // Check if the media query matches or is not available.
    if (!reducedMotionQuery || reducedMotionQuery.matches) {
        scrollBehavior = "auto";
    }
}

function toOne() {
    window.scroll({
        top:  one,
        left: 0,
        behavior: scrollBehavior
    });
}
function toTwo() {
    window.scrollTo({
        top:  two,
        left: 0,
        behavior: scrollBehavior
    });
}
function toThree() {;
    window.scrollTo({
        top:  three,
        left: 0,
        behavior: scrollBehavior
    });
}
function upDown(distance) {
    window.scrollBy({
        top:  distance,
        left: 0,
        behavior: scrollBehavior
    });
}
.block {
    height: 100vh;
}
<!-- requestAnimationFrame polyfill -->
<!--[if IE 9]>
    <script src="https://cdn.jsdelivr.net/npm/raf-polyfill@1.0.0/raf.min.js"></script>
<![endif]-->

<!-- scrollBehavior polyfill for IE and Safari-->
<script>
    if (!('scrollBehavior' in document.documentElement.style)) {
        var js = document.createElement('script');
        js.src = "https://cdn.jsdelivr.net/npm/smoothscroll-polyfill@0.4.4/dist/smoothscroll.min.js";
        document.head.appendChild(js);
    }
</script>

<div id="one" class="block">
    <h1>one</h1>
    <button type="button" onclick="toOne()">To One</button>
    <button type="button" onclick="toTwo()">To Two</button>
    <button type="button" onclick="toThree()">To Three</button>
    <button type="button" onclick="upDown(500)">Down</button>
</div>
<div id="two" class="block">
    <h1>two</h1>
    <button type="button" onclick="toOne()">To One</button>
    <button type="button" onclick="toTwo()">To Two</button>
    <button type="button" onclick="toThree()">To Three</button>
</div>
<div id="three" class="block">
    <h1>three</h1>
    <button type="button" onclick="toOne()">To One</button>
    <button type="button" onclick="toTwo()">To Two</button>
    <button type="button" onclick="toThree()">To Three</button>
    <button type="button" onclick="upDown(-500)">Up</button>
</div>

如果您在 Safari 中打开此 Stackoverflow 页面,您应该能够看到流畅的滚动到操作。要在 Internet Explorer 中查看它,您必须在系统上创建一个页面,因为 Stackoverflow 不支持 IE。


推荐阅读