How can I use scrollTop on the document element to add a background colour on scroll?

In this snippet, we are going to look at how you can modify the background colour of the header element when you scroll. The header element is usually where the navigation for your site will be. This is quite a common design pattern on websites; where the header and thus navigation links sit on top of the above the fold content or hero element. This is because you have control of the background. However, once you start to scroll the main navigation links start to get lost and adding a background to the header navigation really helps to keep the links visible and therefore accessible.

At its most basic implementation, this can be done with only a few lines of code using the onscroll event and the scrollTop property on the HTML element or documentElement. Below is what you will learn and even though at first, it doesn't seem like a lot, it is a good lesson as it introduces you to the DOM and in particular the Document API.

  • The DOM and document interface
  • onscroll and event listeners
  • scrollTop

To go about this you will need to have a page with a fixed header and enough content so that you can scroll the page. Let's get started.

What is the scrollTop and how do we use it?

scrollTop is a property that can be used to get or set the value of how far the top of the element is scrolled. It is a positive number. As such this might be confusing and that's okay as it was for me. So let's have a look at the illustration below.

Image
what is scrollTop illustration showing what value is being returned

The confusion for me was since the element is scrolling up then the number should be negative. This is possibly true since moving items up is usually negative when positioning or transforming, but hey it's not when using scrollTop.

A few other things that must be true are:

  • The element needs to be scrollable or have overflow set to scroll. Because of this, we can use it on the document window as it is scrollable by default. If you want to use scrollTop on other elements you will need to set the overflow of the element to scroll.
  • The HTML document is a special case where the scrollY of the window is returned as the value of scrollTop, this means that you get a value even when the element, the HTML element, is off the top of the screen.

Now we know what the scrollTop property is and what value it returns let's look at how we can use it.

Using scrollTop with a onscroll property (event handler)

Since we know scrollTop returns the value that an element's top moves vertically, we can use it to find out once the element's top has reached a certain position from where it started. What we want to know in our situation is when the content of the body, or HTML to be more correct, has moved to a position above the top that it started at, that is off the screen.

Since we know that the header is 200 pixels high and that the content of the main element is at 250px from the top and there is a 70px top margin on the first element, we can use 320px as the value we want to check for. If you want to know when the content is scrolled under the navigation then subtract 200 from 320 to get 120. Let's make it a little more, say 128px and use that.

Image
calculating scrollTop value to check for in our window scroll function

Please note that these numbers are arbitrary to show how we can use known values to calculate. There is no other meaning in the number or the usage of the CSS properties. In fact, I like to keep most margins to the bottom and have no margin-top.

Using what we know, we can implement the feature where the navigation background colour will change when the content scrolls under it. The following are the steps to make this work:

  1. Make a variable of the element we want to check the scrollTop value of.
    In this case, we are using the HTML so we can use documentElement which is the root element of the DOM.
    var scrollElement = document.documentElement;
  2. Now add an onscroll event to the window and assign a function to it that calls a function.
    window.onscroll = function() { myFunction() };
  3. Manually calculate the value of the scrollTop value (of the element) you want to use and assign it to a variable. See the above illustration or you can also add this snippet and check the log.
      // Check the html element
      var intElemScrollTop = document.documentElement.scrollTop; // document.documentElement Firefox
      console.log('Body Scroll Up: ' + intElemScrollTop);
  4. Next, using a conditional if statement we check when the scrollTop value is greater than the value we want to check, in this case, it is 128.

    If the statement returns true set the header background to a new colour. You could also add a class and have the CSS in the style sheet.
    If the statement returns false remove the style or the class added.

    var scrollElement = document.documentElement; 
    
    window.onscroll = function() { myFunction() };
    
    function myFunction() {
    
      // Note that using the header element won't always work, so you might be better to create a variable from using an ID
      if (scrollElement.scrollTop > 128) {
          header.style.backgroundColor = "rgba(128,255,255,0.7)";
        } else {
          header.style.backgroundColor = "transparent";
        }
    
    }

So now that we can change the background colour of the header element once the scrollTop reaches a certain value we can do anything we like. Why don't you try and modify the height or transform it in some other way and then read on?

Add a class to an element using JavaScript

As stated, you could also add a class and then add a nice transition or animation to the element so that it appears by fade-in or the height adjusts. The sky is the limit!

Here is another code snippet you could add to make the header element height become smaller. It is applied using a CSS class and adding the class to the header element using JavaScript classList.add.

function myFunction() {
 if (scrollElement.scrollTop > 128) {
      header.style.backgroundColor = "rgba(128,255,255,0.7)";
      header.classList.add('small');
    } else {
      header.style.backgroundColor = "transparent";
      header.classList.remove('small')
    }
}
header {
  height: 200px;
  position: fixed;
  width: 100%;
  z-index: 100;
  left: 100px;
  transition: 500ms height;
}
/* You can add any change you want, just make sure the property is in the above rule and you add the transition it to the transition property. */
header.small {
  height: 100px;
}

Thanks for reading and be sure to sign up for the newsletter, I'll be writing more of the same and also doing a give-away every now and again. Bye for now and seize the day!