How to Create Native Smooth Scrolling with JavaScript (or CSS)


A few days ago, I was rendering out a list in Vue that needed some smooth scrolling.

Naturally, I turned to a JavaScript solution, but lo and behold, CSS had me covered.

For simplicity’s sake, suppose we have a navbar that brings us to another section of a webpage.

<nav>
    <ul>
        <a href="#one"><li>One</li></a>
        <a href="#two"><li>Two</li></a>
        <a href="#three"><li>Three</li></a>
    </ul>
</nav>

We also have content to render out.

<div class="content">
    <div id="one"><h1>One</h1></div>
    <div id="two"><h1>Two</h1></div>
    <div id="three"><h1>Three</h1></div>
</div>

Smooth Scrolling using CSS#

In order to demo smooth scrolling, we need to style each page accordingly:

.content div {
  width: 100%;
  height: 100vh;
  text-align: center;
}
nav {
  position: fixed;
}
#one {
  background: #fff;
}
#two {
  background: #e0e0e0;
}
#three {
  background: #fff;
}

The secret here is to add scroll-behavior: smooth; to the <html> element.

html {
  scroll-behavior: smooth;
}

This will give us a basic template for smooth scrolling pages using a navbar. We can also isolate smooth scrolling to different sections of the webpage. It just depends on where you put the scroll-behavior attribute.

Smooth Scrolling using JavaScript#

We can also smooth scroll in JavaScript.

If we know the exact location of the element we want to scroll to, we can scroll to a specific section of the page by using window.scroll() and modifying top.

window.scroll({
  top: 4000,
  left: 0,
  behavior: "smooth",
});

If we know the offset from the current location, we can use window.scrollBy() and, once again, modify top.

window.scrollBy({
  top: 200,
  left: 0,
  behavior: "smooth",
});

I find myself mostly using this last option, where we scroll to a specific element with a combination of document.querySelector() and scrollIntoView().

document.querySelector("#one").scrollIntoView({
  behavior: "smooth",
});