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

kyoshee
3 min readJul 29, 2022

Originally posted on kyoshee.com

Photo by Grant Durr on Unsplash

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

tl;dr

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 querySelectorAll function to avoid storing href attribute and operating on it with slice method. To get target element, let’s select all (actually one, because every id should be unique) elements, that have given href value as their id. querySelectorAll returns an array, and we need the first and only one element.

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!

Result

As a result, I have developed a simple piece of code which is universal — you can use it on every HTML page, and it will work like a charm. This piece of code is reusable, working in every major browsers and it is in vanilla JavaScript. What more do you need for lightweight and performant page?

Thank you for reading,
kyoshee

--

--