Creating A Custom Scroll Bar In 24 Lines Of CSS

Emma Bostian ✨ - Aug 27 '20 - - Dev Community

Have you ever encountered a website with a beautiful scrollbar and thought to yourself “wow, I wish I could create something like that.” Me too! And after a little investigation, I figured out that creating a custom scroll bar for your blog or personal portfolio doesn’t take a ton of CSS.

Today we’ll build a gradient progress bar that fades in from zero opacity to full opacity as you scroll. This tutorial only requires foundational HTML, CSS, and JavaScript knowledge and won’t make use of any JavaScript frameworks or libraries. You can find the full code on CodePen!

HTML.

First let’s create our document structure. Inside of the HTML CodePen editor let’s add two elements: our progress bar and our progress container.

The progress bar will indicate how far down the page the user has scrolled. The progress bar container will span the entire height of the page and contain the progress bar.

Let’s also add a page header with the text “Welcome” and some lorem ipsem paragraphs. I added seven of these paragraphs but for the brevity of this post will only include one.

<h1>Welcome.</h1>
<p>
  Lorem ipsum dolor, sit amet consectetur adipisicing elit. Aspernatur
  provident eveniet veritatis ipsa id consectetur ab tenetur dolores eaque.
  Temporibus laboriosam cum corporis amet doloremque animi aut ipsa ea a?
</p>
Enter fullscreen mode Exit fullscreen mode

Here’s what our web page currently looks like.

HTML page

CSS.

Now we’re ready to add our styles. First let’s add some basic page styling to make our site look a little nicer.

body {
  background: #171414;
  font-family: "Courier New", Courier, monospace;
  color: #ffffff;
  padding: 15% 15% 5%;
}

p {
  font-size: 1.8rem;
}

p:first-of-type {
  margin-top: 100px;
}

h1 {
  font-size: 200px;
  position: absolute;
  top: -5%;
  left: 15%;
  opacity: 25%;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
    Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
}
Enter fullscreen mode Exit fullscreen mode

CSS 1

Next let’s hide the default browser scroll bar. We can use the webkit vendor prefix to hide the scroll bar in Chrome and Safari.

::-webkit-scrollbar {
  width: 0;
  background: transparent;
}
Enter fullscreen mode Exit fullscreen mode

We’ll need to make special considerations for Firefox as it’s not a webkit browser and won’t respond to the webkit vendor prefix (like Chrome and Safari).

html {
  scrollbar-width: none;
}
Enter fullscreen mode Exit fullscreen mode

Now we’re ready to style our custom scroll bar. First let’s set up our scroll bar container. We want our scroll bar container to be fixed to the right side of the viewport so we’ll use position fixed with top and right values set to 0. We’ll give the scroll container a width of ten pixels and a very light grey background.

#progressBarContainer {
  position: fixed;
  top: 0;
  right: 0;
  width: 10px;
  height: 100%;
  background: rgba(255, 255, 255, 0.05);
}
Enter fullscreen mode Exit fullscreen mode

You should now see the scroll container appearing on the right side of the viewport.

CSS 2

Our progress bar will also be fixed to the right side of the viewport and have a width of ten pixels, however, we’ll give it a linear gradient from red to violet in order to make it stand out.

#progressBar {
  position: fixed;
  top: 0;
  right: 0;
  width: 10px;
  background: linear-gradient(to top, violet, red);
  height: 100%;
  opacity: 100%;
}
Enter fullscreen mode Exit fullscreen mode

CSS 3

We want to dynamically update the height and opacity of our progress bar on scroll so let’s set height and opacity to zero.

#progressBar {
  position: fixed;
  top: 0;
  right: 0;
  width: 10px;
  background: linear-gradient(to top, violet, red);
  height: 0;
  opacity: 0;
}
Enter fullscreen mode Exit fullscreen mode

JavaScript.

To update the height and opacity of our progress bar we’ll need to write a few lines of JavaScript. Let’s first grab our progress bar DOM node.

const progressBar = document.querySelector("#progressBar");
Enter fullscreen mode Exit fullscreen mode

We’ll also need to calculate the total height of our web page. We can calculate the total height by subtracting the window inner height from the entire document body scroll height.

let totalPageHeight = document.body.scrollHeight - window.innerHeight;
Enter fullscreen mode Exit fullscreen mode

Next, let’s add an event listener to the window. When we scroll we want to calculate the new progress height. We can calculate this by first dividing the window’s page Y offset by the total page height to get a decimal fraction. To use this value in our CSS code we must multiply this fraction by 100 (to get a percentage).

Lastly, we can set the progress bar’s height and opacity to the new progress height.

Unfamiliar with the ${} syntax? It’s called a template string or template literal and it allows you to combine evaluated expressions (the values between the ${}) with plain strings.

window.onscroll = () => {
  let newProgressHeight = (window.pageYOffset / totalPageHeight) * 100;
  progressBar.style.height = `${newProgressHeight}%`;
  progressBar.style.opacity = `${newProgressHeight}%`;
};
Enter fullscreen mode Exit fullscreen mode

Conclusion.

And that’s it! You now have a beautiful custom scroll bar in just a few lines of CSS.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .