Check out my blog for more articles or Github for my free-to-read JavaScript Ebook that covers all the new features from ES6 to 2019.
If you want find a great place for interactive tutorials, i recommend Educative (Disclaimer: the link it's affiliate) where I'm currently finishing to build my JavaScript course.
Create a simple smooth scrolling page navigation
Having a navbar with links to different part of the page is a very common feature of many websites. Being able to smoothly scroll the page instead of jumping to the desired section can make the difference from a pleasant user experience to an annoying one. In this short tutorial we will look at how to implement a simple smooth scrolling navbar in your web page.
The result
The Task
- Difficulty: Beginner
- Duration: < 1 hour
- Tools: Text Editor of your choice
- Github Repo: https://github.com/AlbertoMontalesi/InspiredWebDev-Tutorials
The HTML
The structure of the page that we will create is very simple: - a navigation bar with three links - a content area with three sections Start by copying the code below inside the body
tag of your html file.
<!-- navigation -->
<div id="navigation">
<span><a href="#sectionLink1">
Go to section 1
</a></span>
<span><a href="#sectionLink2">
Go to section 2
</a></span>
<span><a href="#sectionLink3">
Go to section 3
</a></span>
</div>
<!-- content -->
<div id="content">
<div id="section1">Section 1</div>
<div id="section2">Section 2</div>
<div id="section3">Section 3</div>
</div>
As you can see, our a
tags have an href
that is not exactly the same as the id
of the target area. If we were to write href="section1"
upon clicking the link, the page would jump straight to the content and we don't want that, we want it to scroll smoothly therefore we use a similar, albeit different naming, to avoid this automatic behavior that we plan to override.
The CSS
If you were to look at the page right now you would see that it looks nothing like the one in the result gif. Let's open our style.css
file and copy this code inside.
/* basic styling to make the links bigger */
#navigation {
display: flex;
/* make the navbar alway stay on top */
position: fixed;
top: 0;
width: 100%;
background-color: white;
}
#navigation span {
flex-grow: 1;
height: 50px;
border: 1px solid black;
display: flex;
justify-content: center;
align-items: center;
}
#navigation span a {
display: inline-block;
}
/* when a link is clicked, it gets highlighted */
.highlighted {
color: red;
}
/* make each section taller and give them different colors */
#content {
margin-top: 50px;
}
#content div {
height: 100vh;
/* align the text in the middle */
display: flex;
justify-content: center;
align-items: center;
font-size: 3rem;
font-weight: bold;
}
#section1 {
background-color: lightcoral;
}
#section2 {
background-color: lightblue;
}
#section3 {
background-color: lightgreen;
}
The code itself is pretty self explanatory, you can look at the comments to clarify any doubt.
The JavaScript
Now, for the most important part of the tutorial, let's stop for a second and think of how to achieve the result that we want. We need to add an event listener to each of our links and connect them to the target sections, adding a smooth scroll behavior.
document.addEventListener("DOMContentLoaded", () => {
// little hack to detect if the user is on ie 11
const isIE11 = !!window.MSInputMethodContext && !!document.documentMode;
// get all the links with an ID that starts with 'sectionLink'
const listOfLinks = document.querySelectorAll("a[href^='#sectionLink");
// loop over all the links
listOfLinks.forEach(function (link) {
// listen for a click
link.addEventListener('click', () => {
// toggle highlight on and off when we click a link
listOfLinks.forEach( (link) => {
if (link.classList.contains('highlighted')) {
link.classList.remove('highlighted');
}
});
link.classList.add('highlighted');
// get the element where to scroll
let ref = link.href.split('#sectionLink');
ref = "#section" + ref[1];
// ie 11 does not support smooth scroll, so we will simply scroll
if (isIE11) {
window.scrollTo(0, document.querySelector(ref).offsetTop);
} else {
window.scroll({
behavior: 'smooth',
left: 0,
// top gets the distance from the top of the page of our target element
top: document.querySelector(ref).offsetTop
});
}
})
})
})
You can see that I have included a small trick to make our code work on Internet Explorer 11. Despite it being a very niche website, if you happen to be working on an enterprise software you will probably have to deal with it at one point so I figured it was worth giving you a hand on that. IE11 does not support smooth scrolling and if you remember, at the beginning of the tutorial I explained why we used different naming for the a
tag and our div
so, since we are 'disabling' the default click behavior, here we need to manually implement our own version of it to make the click of a button bring the user to the correct section. Enough of IE11, let's look at the code from closer:
listOfLinks.forEach(function (link) {
// listen for a click
link.addEventListener('click', () => {
// toggle highlight on and off when we click a link
listOfLinks.forEach( (link) => {
if (link.classList.contains('highlighted')) {
link.classList.remove('highlighted');
}
});
link.classList.add('highlighted');
First we take all of our a
tag that we used in the navigation and we toggle a css class to style them differently upon click.
let ref = link.href.split('#sectionLink');
ref = "#section" + ref[1];
// ie 11 does not support smooth scroll, so we will simply scroll
if (isIE11) {
window.scrollTo(0, document.querySelector(ref).offsetTop);
} else {
window.scroll({
behavior: 'smooth',
left: 0,
// top gets the distance from the top of the page of our target element
top: document.querySelector(ref).offsetTop
});
}
Next, we store in the ref
variable the number of the link that was clicked and we construct the target section with ref = "#section" + ref[1];
After that, it is simply a matter of creating the scroll action by adding a behavior and the coordinates of our section. Perfect ! You know now how to create a smooth scrolling navigation on your website.
Go ahead and implement it your way and feel free to share here a link to your attempt / project.
Thank you very much for reading. Follow me on DevTo or on my blog at inspiredwebdev for more.
Top comments (5)
CSS:
it doesn't support in many browser
This is what I like. Pure CSS and Javascript.
Thank you!
Thank you!
Smooth scrolling behaves differently in Chrome and Firefox