JS – Smooth scrolling without jQuery

You know what link anchors are, correct? They are used to jump between different sections of the same page. Quite often when a link anchor is clicked, the page smoothly scrolls to the desired location. However, smooth scrolling is not the native behavior. No, the native behavior for link anchors is to instantly jump between sections, which can be jarring and unpleasant. That is why many developers smooth it out using jQuery scripts like this one.

I too enjoy it when anchor links smoothly scroll, but for the last few months I have on a “jQuery fast” and it has severely limited my smooth scrolling options. Smooth scrolling is impossible to recreate with CSS transitions, I have had limited success using requestAnimationFrame, and fun scroll-to-top buttons like Elevator.js are not appropriate. I have really been in the dark on filling the hole left by removing jQuery.

Yesterday while working on my capstone project, I decided I would implement the required scroll to top button (which is a link anchor). As I am also not using jQuery for this site, I again went on a search for an effective smooth scrolling replacement. This time around, unlike previous searches, I found some things I did not expect.

First, I came across a new, bleeding-edge CSS property: scroll-behavior. This property is so bleeding-edge it is not listed on caniuse.com. With the property applied, any time you click a link anchor the page will natively smooth-scroll to that position. The only catch is it does not work with unnamed (“#”) anchors; it must be a named (“#top”) anchor, which is not that big of a deal. Normally I am not one who uses such experimental features in live sites, especially as it is only currently supported by Firefox desktop and Chrome (behind a flag), but I was really excited by its existence and applied it to my capstone site as follows.

html {
  /* Bleeding-edge native smooth-scrolling
  https://drafts.csswg.org/cssom-view/#smooth-scrolling */
  scroll-behavior: smooth;

Being the responsible developer I am, having effectively only one browser support native smooth scrolling was not satisfactory. I needed a fallback. That is when I came across the promising Smooth Scroll JavaScript library. The documentation is very clear so I will not explain it. I loaded the script and tested it, and it delightfully worked like a charm.

Now I had a choice. Do I use this library regardless and forget the experimental native feature or keep both and use graceful degradation? I cannot have both working at the same time and conflicting with each other.

Not about to give up my super-cool native method, I went for the graceful degradation route. As it would happen, there was an open issue on the Smooth Scrolling repo referring to detecting native support and using the native APIs instead of the library. After minor adaptations to the code given in the issue, I ended up with the following feature-detection snippet.

// If native smooth scrolling is not present, fallback
if (document.documentElement.style.scrollBehavior === undefined) {

I now have the best of both worlds: experimental native scrolling and a really nice JavaScript library as fallback. The anchor links on both my capstone and personal site have never been so smooth scrolling and jQuery free. 😀