How to add smooth scrolling to every anchor element on a page

Ever needed a smooth scroll when clicking on a elements? I am here to help!

TL;DR: code snippet.

Overview

We need for a page to scroll smoothly when clicking on anchor that leads to some element with given id. So we need our anchor element, our target element and a function to scroll a page up ⬆️ (or down ⬇️) to target element. What a relief — we can achive that with vanilla JavaScript using built-in functions!

Theory

Retrieving anchors

Since only anchors with set href attribute as id of some other element scrolls page to that other element, we can only perform smooth scrolling with that anchors. How can we find them? They have something in common: that being href attribute starting with ‘#’, so we can easily collect them using “attribute starting with” selector. Our attribute will be ‘href’ and it must start with a ‘#’: document.querySelectorAll('[href^=#]'). More on this function on MDN.

Iterating over NodeList

Some ways you can iterate over NodeList are described on corresponding MDN page. I decided to use Object’s built-in method entries to get an array of pairs [key, value] and iterate over it with forEach() Array method. In forEach(), thanks to developing JavaScript, we can extract that [key, value] values from pair: [key, value] = [ 'iamkey', 'iamvalue' ].

Adding events

This one is simple: add on click event that scrolls us to target element. Doing that we will override default behavior, so I recommend adding event.preventDefault() to callback.

JavaScript has built-in function that will scroll document to desired position measured from top of the document in pixels. To add behavior: 'smooth’ we must pass an options object with set top and behavior values.

How to get target element position

Firstly, we need to get that element. I am using querySelector() function to avoid storing href attribute and operating on it with slice method.

To get element’s relative position from top of the document, we can getBoundingClientRect() of that element and retrieve top value. To add some space above for better readability, better scroll to just before the target element (let it be 50 pixels). Now we can smoothly scroll up to desired element!


Code snippet.
$ cd ..