Search code examples
horizontal-scrollingsmooth-scrollingscrolltovertical-scrollingsnap

element.scrollTo smooth scrolling not working in Safari in snappable scrollable container


I'm creating a thumbnails slider and wanted to use snap scrolling and scrollTo. When I select a thumbnail, I want an other scrollable container to scroll to the image with an id linked to by this thumb. I want the scrolling to be visible, not just a "jump" to the image. This all works fine in Firefox, Chrome and others.

However, I know that scrollTo has limited support in Safari up until 14.7, but even in the most recent version I cannot recreate the smooth scrolling behavior. https://caniuse.com/?search=scrollto

I created a CodePen to demonstrate my problem https://codepen.io/Bregt/pen/jOwJGMJ

I added the following CSS to my horizontal scrollable container.

.h {
    display: flex;
    overflow-x: auto;
    overflow-y: hidden;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    width: 200px;
}

.h > * {
    width: 100%;
    flex-shrink: 0;
    scroll-snap-align: start;
    scroll-snap-stop: always;
}

In my JavaScript, I fetch the element with a certain ID, and then use scrollTo on the container

document.querySelector(".js-h-slide").addEventListener("click", (e) => {
  let element = document.getElementById("h-image-5");  
  document.querySelector(".js-h-slides").scrollTo({
    left: element.offsetLeft,
    behavior: "smooth"
  })
});

What did I forget?


Solution

  • This behavior is apparently possible, but behind a flag. I'm confused though by what is mentioned at Can I Use about scrollTo.

    This is the info I found at WebKit http://bugs.webkit.org/show_bug.cgi?id=188043

    In the end, I used the 'smoothscroll-polyfill' polyfill that I dynamically import. (https://github.com/iamdustan/smoothscroll) :(

    if (!('scrollBehavior' in document.documentElement.style)) {
        import('smoothscroll-polyfill').then((module) => {
            module.polyfill();
        }).then(() => {
            ...
        });
    }