52

I'm working on a single page portfolio which is navigated using a top-mounted navigation bar using href's. I use scroll-behavior: smooth; in my head's CSS and this makes the navigating smooth and pleasant to look at when looking at it in chrome. When loading the site using Safari this behavior is lost and the navigation is instant. Is there a Safari equivalent to this CSS functionality?

Florian Schut
  • 662
  • 1
  • 5
  • 13

8 Answers8

35

Safari does not support scroll-behavior: smooth, you'll need some custom javascript to achieve the same effect. See this: Javascript - window.scroll({ behavior: 'smooth' }) not working in Safari

Aditya Thakur
  • 2,562
  • 2
  • 10
  • 21
  • 4
    Or just use the polyfill, as mentioned in the linked thread: https://github.com/iamdustan/smoothscroll – Stan Hebben Feb 29 '20 at 10:09
  • 11
    I can confirm, the polyfill works great for me, as of today 4th june 2020, just load before your own stuff: `` – elmcrest Jun 04 '20 at 20:22
  • @poulter7 works like a charm for me on all apple platforms. – elmcrest Jul 08 '20 at 09:15
  • @poulter7 ... see my production environment raesener.de if you like. – elmcrest Jul 08 '20 at 09:30
  • 4
    Safari 15.4 will include smooth scroll support: https://caniuse.com/css-scroll-behavior https://developer.apple.com/documentation/safari-release-notes/safari-15_4-release-notes#Web-API – jeerbl Mar 09 '22 at 15:33
  • 1
    Here is the answer that should be pinned: https://stackoverflow.com/a/71411937/2418066 – jeerbl Mar 09 '22 at 15:37
  • @elmcrest then how to import it on js file? – Ashik Jun 20 '22 at 13:22
  • @Ashik that depends on your setup and is related to general development with JS, so the topic is "js imports" I'd suggest. besides, just use the html tag. – elmcrest Jun 21 '22 at 14:24
  • I am using jquery, I don't want to use import export. for example in wow js I am using var wow = new Wow() in js file. Is there any way to do like that? – Ashik Jun 22 '22 at 05:29
17

Safari 15.4 adds support for CSS scroll-behavior as detailed in the 15.4 release notes.

Added support for the CSS scroll-behavior property and ScrollOptions, allowing smooth scrolling to anchors or via JavaScript.

jeerbl
  • 7,537
  • 5
  • 25
  • 39
8

2022 Update

Safari support for smooth-scroll is still broken and not customizable.

If you're looking for a simple way to enable it, you can take a look at the API I've been building for the past 4 years: https://github.com/CristianDavideConte/universalSmoothScroll.

It's extremly fast, easy to use and it enables smooth-scroll on basically every browser (IE is not supported) with high customization degree (easing, duration, interruptibility, etc...).

Below you'll find an example of how to use the API to quickly enable smooth-scroll on your website:

Edit:

Since from UniversalSmoothScroll 6.0.0 the Ease-Functions library has been converted to a module, this answer has been updated to make it work on stackoverflow.
The problem is that stackoverflow doesn't support modules in the javascript section of snippets, so you'll find a workaround to make it work: you can ignore it since in a normal website you wouldn't use it.

/*
 * In this example we will only customize the document's scrolling,
 * but the API fully support every custom scrollable container
 */
function init() {
  /* 
   * We tell the API which element is the one that scrolls the document
   * (useful whenever it's something like the body element, a custom container,
   * a framework specific container, etc...)
   */
  uss.setPageScroller(window); 

  /** 
   * This API function, enables the anchors' 
   * smooth-scrolling to the corresponding section
   */
  uss.hrefSetup();  
  
  /**
   * This API function, sets the easing of the pageScroller (that we set to window) to a
   * medium speed(the "QUART" part) ease-in-out function that last exactly 1 second.
   */
   uss.setStepLengthCalculator(EASE_IN_OUT_QUART(1000)); 
   
   /**
    * This API function allow us to stop the scrolling on a container.
    * In this case, we don't want any more scrolling 
    * if the user scrolls the document with the mousewheel.
    */
    window.addEventListener(
          "wheel", 
          () => uss.stopScrolling(window) 
    ); 
}



/*
 * YOU CAN IGNORE THIS PART.
 * This is just part of the workaround used on stackoverflow to make modules work. 
 * Basically it loads the init function whenever the document is fully loaded and the module is imported.
 * Check out this discussion for more informations: https://meta.stackoverflow.com/questions/389108/support-javascript-es6-modules-in-code-snippets
 */
document.addEventListener("readystatechange", () => document.readyState === "complete" && init());
/* Just styling, none of this is necessary for the API */
html, body {
  margin: 0;
}

nav {
  display: flex;
  justify-content: center;
  position: fixed;
  margin-top: 0;
  width: 100vw;
}

nav > a {
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  text-decoration: none;
  height: 20vh;
  width: 15vw;
  background: rgba(20,20,20,0.5);
  transition: all 0.3s;
}

nav > a:hover {
  background: rgba(20,20,20,0.6);
}

.horizontal-container {
  display:flex;
}

.page {
  width: 100vw;
  height: 100vh;
  flex-shrink: 0;
}

#to1 {
  background: linear-gradient(135deg, rgba(2,0,36,1) 0%, rgba(9,9,121,1) 0%, rgba(0,212,255,1) 100%);
}


#to2 {
  background: linear-gradient(225deg, rgba(121,9,9,1) 0%, rgba(255,42,0,1) 100%);
}


#to3 {
  background: linear-gradient(45deg, rgba(227,176,7,1) 0%, rgba(255,239,0,1) 100%);
}


#to4 {
  background: linear-gradient(315deg, rgba(7,101,6,1) 0%, rgba(0,255,98,1) 100%);
}
<html>

  <head>
    <!-- We include the API -->
    <script src = "https://cdn.jsdelivr.net/npm/universalsmoothscroll@latest/universalsmoothscroll-min.js"></script>
    <!-- We include the API's easing library (this is optional) -->
    <script src = "https://cdn.jsdelivr.net/npm/universalsmoothscroll@latest/universalsmoothscroll-ease-functions-min.js" type = "module"></script>
    
    <!-- 
      YOU CAN IGNORE THIS PART.
      This is just part of the workaround used on stackoverflow to make modules work.  
      It import the module and turns the import into a global variable.
      Check out this discussion for more informations: https://meta.stackoverflow.com/questions/389108/support-javascript-es6-modules-in-code-snippets
     -->
    <script type = "module">
      import {EASE_IN_OUT_QUART} from "https://cdn.jsdelivr.net/npm/universalsmoothscroll@latest/universalsmoothscroll-ease-functions-min.js";
      window.EASE_IN_OUT_QUART = EASE_IN_OUT_QUART;
    </script>
  </head>


  <body>
    <nav> <!-- header -->
      <a href="#to1"><p>Blue</p></a>
      <a href="#to2"><p>Red</p></a>
      <a href="#to3"><p>Yellow</p></a>
      <a href="#to4"><p>Green</p></a>
    </nav>
    <!-- Website pages -->
    <div class="horizontal-container">
      <div id="to1" class="page"></div>
      <div id="to2" class="page"></div>
    </div>
    <div class="horizontal-container">
      <div id="to3" class="page"></div>
      <div id="to4" class="page"></div>
    </div>
  </body>

</html>

More usage examples can be found at: this answer and the official playground or my website.

Cristian Davide Conte
  • 1,231
  • 1
  • 8
  • 25
7

According to the comment of elmcrest, it works.

<script defer src="https://unpkg.com/smoothscroll-polyfill@0.4.4/dist/smoothscroll.min.js"></script>
Nicolas
  • 530
  • 6
  • 9
2

you can solve the problem like that:

jQuery('html, body').animate({
        scrollTop: $('html').offset().top
      }, 800)
LikapaTR
  • 67
  • 1
  • 2
  • 6
1

Using jquery there is a equivalent for scroll-behavior: smooth.

Try this:

$('html, body').animate({
    scrollTop: 0
}, 1500);

Chanze zero to you desired postion.

Derzu
  • 7,011
  • 3
  • 57
  • 60
1

$('a[href*="#"]').not('[href="#"]').not('[href="#0"]').click(function (t) {
    if (location.pathname.replace(/^\//, "") == this.pathname.replace(/^\//, "") && location.hostname == this.hostname) {
        var e = $(this.hash);
        e = e.length ? e : $("[name=" + this.hash.slice(1) + "]"), e.length && (t.preventDefault(), $("html, body").animate({
            scrollTop: e.offset().top
        }, 600, function () {
            var t = $(e);
            if (t.focus(), t.is(":focus")) return !1;
            t.attr("tabindex", "-1"), t.focus()
        }))
    }
});
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Feb 03 '22 at 08:48
0

Although it is stated here that safari supports scroll with smooth https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-behavior but even example doesn't work on safari

As a way out, I found a library with a polyfills, and in those browsers where it does not work it's replaced - https://github.com/iamdustan/smoothscroll

Alex Pilyavskiy
  • 140
  • 1
  • 3