'Javascript vertical scrolling function

I am trying to detect a scroll on my page using JavaScript. So that I can change classes and attributes of some elements when user has scrolled certain amount of page. This is my JS function:

    function detectScroll() {
    var header = document.querySelector(".headerOrig"),
        header_height  = getComputedStyle(header).height.split('px')[0],
        fix_class = "changeColor";

    if( window.pageYOffset > header_height ) {      
        header.classList.add(fix_class);
    }
    if( window.pageYOffset < header_height ) {
        header.classList.remove(fix_class);
    }
    var change = window.setInterval(detectScroll, 5000);
}

and I am calling it when the page is loaded:

<body onload="detectScroll();">

However, I have this problem - I need to set up a really small interval so that the function gets called and the class is changed immediately. BUT then the page freezes and everything except the JS function works very slowly. Is there any better way of achieving this in JavaScript?

Thanks for any advice/suggestion.



Solution 1:[1]

You are going to want to change a couple things. First, we can use onscroll instead of an interval. But you are also going to want to cache as much as possible to reduce the amount of calculations on your scroll. Even further, you should use requestAnimationFrame (or simply "debounce" in general for older browsers -- see the link). This ensures your work only happens when the browser is planning on repainting. For instance, while the user scrolls the actual scroll event may fire dozens of times but the page only repaints once. You only care about that single repaint and if we can avoid doing work for the other X times it will be all the more smoother:

// Get our header and its height and store them once
// (This assumes height is not changing with the class change).
var header = document.querySelector(".headerOrig");
var header_height  = getComputedStyle(header).height.split('px')[0];
var fix_class = "changeColor";

// This is a simple boolean we will use to determine if we are
// waiting to check or not (in between animation frames).
var waitingtoCheck = false;

function checkHeaderHeight() {
  if (window.pageYOffset > header_height) {      
    header.classList.add(fix_class);
  }
  if (window.pageYOffset < header_height) {
    header.classList.remove(fix_class);
  }
  // Set waitingtoCheck to false so we will request again
  // on the next scroll event.
  waitingtoCheck = false;
}

function onWindowScroll() {
  // If we aren't currently waiting to check on the next
  // animation frame, then let's request it.
  if (waitingtoCheck === false) {
    waitingtoCheck = true;
    window.requestAnimationFrame(checkHeaderHeight);
  }
}

// Add the window scroll listener
window.addEventListener("scroll", onWindowScroll);

Solution 2:[2]

use onscroll instead of onload so you don't need to call the function with an interval. Your dedectScroll function will be triggered automatically when any scroll appers if you use onscroll

<body onscroll="detectScroll();">

Solution 3:[3]

Your function is adding an interval recursively, you should add an event listener to the scroll event this way :

function detectScroll() {
    var header = document.querySelector(".headerOrig"),
        header_height  = getComputedStyle(header).height.split('px')[0],
        fix_class = "changeColor";

    if( window.pageYOffset > header_height ) {      
        header.classList.add(fix_class);
    }
    if( window.pageYOffset < header_height ) {
        header.classList.remove(fix_class);
    }

}
window.addEventListener("scroll",detectScroll);

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 semirturgay
Solution 3 n00dl3