Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

window.scroll smooth not working on Safari

I'm using this to get a smooth scroll to a particular section when a user clicks on a button:

window.scroll({
  top: $(this).data('y'),
  left: 0,
  behavior: 'smooth'
});

This works great everywhere (including Android phones) but on Safari (desktop and iphone). In those cases it scrolls to the correct position but it isn't smooth, it's like it jumps.

I made a small demo on Codepen available here. Just click on the nav menu options and it will scroll there. This will be smooth on Chrome but not on Safari.

Is this not supported? (it doesn't seem to be the case looking at the doc) What are the supported options?

Thanks!

like image 227
moondaisy Avatar asked Aug 07 '18 16:08

moondaisy


People also ask

Does smooth scrolling work on Safari?

Unfortunately, the smooth option is not supported by Safari (Element.

How do I make Windows scroll smooth?

Now you can use just window. scrollTo({ top: 0, behavior: 'smooth' }) to get the page scrolled with a smooth effect.

How do I fix smooth scrolling?

If your Google Chrome seems to be jerky or stuttering when scrolling, you can enable this feature. Open a new tab and type chrome://flags/#smooth-scrolling in the address bar, and press Enter. Click the dropdown box next to Smooth scrolling, and click Enabled. Click Relaunch on the bottom-right corner.

Should I enable smooth scrolling?

Enabling a smooth scroll allows you to scroll like that with your regular wheel scroll. Smooth scrolling is also useful with keyboard shortcuts. When this feature is enabled, pressing the Page Down button won't just jump directly down one page.


3 Answers

window.scroll is supported, but scroll-behavior CSS is not.

https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-behavior

Pending support, consider using the smoothscroll-polyfill which adds smooth scrolling support for Safari, IE, and Edge.

like image 165
tyriker Avatar answered Sep 23 '22 16:09

tyriker


I recently wrote down my ideas into a function, which is kind of polyfill for lacking smooth scroll feature support in IOS browsers and desktop Safari as well. Some may call it a bloody workaround, but hey, it's working. It doesn't require jQuery, it's pure javascript.

var fnc_scrollto = function(to,id){
    var smoothScrollFeature = 'scrollBehavior' in document.documentElement.style;
    var articles = document.querySelectorAll("ul#content > li"), i;
    if (to == 'elem') to = articles[id].offsetTop;
    var i = parseInt(window.pageYOffset);
    if ( i != to ) {
        if (!smoothScrollFeature) {
            to = parseInt(to);
            if (i < to) {
                var int = setInterval(function() {
                    if (i > (to-20)) i += 1;
                    else if (i > (to-40)) i += 3;
                    else if (i > (to-80)) i += 8;
                    else if (i > (to-160)) i += 18;
                    else if (i > (to-200)) i += 24;
                    else if (i > (to-300)) i += 40;
                    else i += 60;
                    window.scroll(0, i);
                    if (i >= to) clearInterval(int);
                }, 15);
            }
            else {
                var int = setInterval(function() {
                    if (i < (to+20)) i -= 1;
                    else if (i < (to+40)) i -= 3;
                    else if (i < (to+80)) i -= 8;
                    else if (i < (to+160)) i -= 18;
                    else if (i < (to+200)) i -= 24;
                    else if (i < (to+300)) i -= 40;
                    else i -= 60;
                    window.scroll(0, i);
                    if (i <= to) clearInterval(int);
                }, 15);
            }
        }
        else {
            window.scroll({
                top: to,
                left: 0,
                behavior: 'smooth'
            });
        }
    }
};

You may pass arguments to the function as numeric value (scollTo-position in pixels) or as a call of an element with index (in my case LI nodes in an UL --> "articles").

<a class="active" href="javascript:fnc_scrollto(0)">Home</a>
<a class="active" href="javascript:fnc_scrollto(457)">anywhere</a>
<a href="javascript:fnc_scrollto('elem',0)">element 1</a>
<a href="javascript:fnc_scrollto('elem',1)">element 2</a>

You may play around with the numbers to adapt the smooth effect to your needs. If you have a sticky navbar on top, you need to adapt the line

if (to == 'elem') to = articles[id].offsetTop;

to your needs like e.g.

if (to == 'elem') to = parseInt(articles[id].offsetTop-navbar.clientHeight);

Hope you like it :-)

like image 31
ddlab Avatar answered Sep 26 '22 16:09

ddlab


More specifically in a JavaScript context, the unsupported part is the behavior parameter on scrollToOptions as detailed here:

https://developer.mozilla.org/en-US/docs/Web/API/Window/scroll

like image 21
EoghanM Avatar answered Sep 24 '22 16:09

EoghanM