theJuls
theJuls

Reputation: 7470

How to do a smooth scrollTo (or equivalent) on Safari?

I have a simple app that I need to have a smooth scroll up a certain page.

This works all fine and well on Chrome, but on Safari I get an abrupt jump back to the top when I need a smooth scroll transition.

According to the MDN documentation the scrollTo with options indeed is not available for Safari. Since this is the case, how could I get this equivalent effect to work for it?

Here is a sample app of what I currently have using just a simple .scrollTo([options]) call.

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>

Upvotes: 2

Views: 396

Answers (1)

Rich DeBourke
Rich DeBourke

Reputation: 3423

If you want to do a smooth (or animated) scroll to a position on your page using the JavaScript functions scroll, scrollTo, or scrollBy in all browsers (including IE 9 and up and Safari) and you’re not loading jQuery, then the iamdustan smoothscroll polyfill might be the easiest way to add the functionality.

You can either include the polyfill in the page’s head section and server it to every user (it’s only around 1,400 bytes when gzipped) or you can do a test and if the polyfill is needed, add it to the page.

The smoothscroll polyfill is available from the jsdelivr.net CDN.

For IE9, a polyfill for requestAnimationFrame for handling the animation is also required. Since IE9 users are becoming rare, it’s probably easier to use an IE conditional to load a the polyfill from your own server.

I included some code to use auto instead of smooth for the scrolling if the user has their system setup for prefers-reduced-motion: reduce.’ I do ignore prefers-reduced-motion` on Internet Explorer as IE11 was reporting it was off when it was on (but IE9, using a polyfill for window.matchMedia, was reporting it correctly). My assumption is that anybody who needs accessibility settings will be using one of the newer browsers.

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/[email protected]/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/[email protected]/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>

If you open this Stackoverflow page in Safari, you should be able to see the smooth scrollTo in action. To see it in Internet Explorer, you have to create a page on your system as Stackoverflow doesn't support IE.

Upvotes: 2

Related Questions