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",
});