How To Create Custom ScrollBar with CSS and JavaScript

In this article, we are going to create a custom scrollBar. Our Custom ScorllBar will display the gradient color progress on page scroll. We are not going to use any javascript framework like jQuery, etc. Only basic HTML, CSS and Vanilla JavaScript. If you are interested then take a look to the similar but horizontal progress bar in React Js.

Let’s get started with basic HTML.

HTML

The first step is to create the progress bar container. It’s very basic HTML because CSS and JavaScript will going to handle this progress bar.

<div id="progressBarContainer">
  <div id="progressBar"></div>
</div>

Now add some paragraphs to this HTML. We are using the Lorem ipsum dummy content to generate the paragraph.

<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>
<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>
<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>
<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>
<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>
<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>
<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>

CSS

The next step is to add some CSS styles to make the looks good.

html {
  overflow: -moz-scrollbars-none;
  scrollbar-width: none;
}

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

p {
  font-size: 1.8rem;
}

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

::-webkit-scrollbar {
  display: none;
}

Let’s style our progress bar container and the progress bar.

#progressBarContainer {
  position: fixed;
  z-index: 10;
  background: rgba(255, 255, 255, 0.05);
}


#progressBar {
  position: absolute;
  will-change: transform, opacity;
  background: linear-gradient(to top, violet, red);
  transform-origin: top center;
  transform: scale(1, 0);
  opacity: 0;
}

#progressBarContainer,
#progressBar {
  top: 0;
  right: 0;
  bottom: 0;
  width: 10px;
}

JavaScript

Let’s move to the JavaScript part. Now select the progress bar with document.querySelector() and detected the total page height.

const progressBarContainer = document.querySelector("#progressBarContainer");
const progressBar = document.querySelector("#progressBar");
let totalPageHeight = document.body.scrollHeight - window.innerHeight;
let debounceResize;

We will come later to the debounceResize variable and let’s define our first event listener for page scroll. We are going to use the scroll listener and will apply the transform and opacity style through JavaScript.

window.addEventListener("scroll", () => {
  let newProgressHeight = window.pageYOffset / totalPageHeight;
  progressBar.style.transform = `scale(1,${newProgressHeight})`;
  progressBar.style.opacity = `${newProgressHeight}`;
}, {
  capture: true,
  passive: true
});

capture: A Boolean indicating that events of this type will be dispatched to the registered listener before being dispatched to any EventTarget beneath it in the DOM tree.

passive: A Boolean that, if true, indicates that the function specified by listener will never call preventDefault(). If a passive listener does call preventDefault(), the user agent will do nothing other than generate a console warning.

https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener

Next listener, we have to define for the progress bar container. If you click on a certain position then content should scroll too. So we are going to apply the click event listener on the progress bar container.

progressBarContainer.addEventListener("click", (e) => {
  let newPageScroll = e.clientY / progressBarContainer.offsetHeight * totalPageHeight;
  window.scrollTo({
    top: newPageScroll,
    behavior: 'smooth'
  });
});

Our scroll bar gets break on resizing the window because it won’t get the total page height on page resize. So now we have to add the last event listener on page resize. We are going to use the debounceResize variable that we are going to use for the setTimeout() event.

window.addEventListener("resize", () => {
  clearTimeout(debounceResize);
  debounceResize = setTimeout(() => {
    totalPageHeight = document.body.scrollHeight - window.innerHeight;
  }, 250);
});

We hope this article to create custom scroll bar with CSS and JavaScript. If you like this article then please follow us on Facebook and Twitter.