Home > front end >  Why does my scroll function work with IDs but not classes?
Why does my scroll function work with IDs but not classes?

Time:07-11

I'm trying to add (not replace) a class to multiple elements when scrolling down 10px. I need to target multiple IDs in some HTML that I have no way of changing. These elements do share a few classes though, so I thought I could just target one of those instead.

When I use getElementById, it runs just fine and adds a class to a single ID. If I use getElementsbyClassName or querySelectorAll to target a class, it won't work.

This one works:

tabs = document.getElementById("intro");

scrollFunc = function() {
  var y = window.scrollY;
  if (y >= 10) {
  tabs.classList.add("scrollNav");
              }
  else {
    tabs.classList.remove("scrollNav");
  }
};

window.addEventListener("scroll", scrollFunc);

This one doesn't:

tabs = document.getElementsByClassName("navTabs");
    
    scrollFunc = function() {
      var y = window.scrollY;
      if (y >= 10) {
      tabs.classList.add("scrollNav");
                  }
      else {
        tabs.classList.remove("scrollNav");
      }
    };
    
    window.addEventListener("scroll", scrollFunc);

CodePudding user response:

You must loop over each element in the collection that getElementsByClassName returns.

Try:

tabs = document.getElementsByClassName("navTabs");

scrollFunc = function() {
  var y = window.scrollY;
  if (y >= 10) {
  [...tabs].forEach((tab) => {
     tab.classList.add("scrollNav");
  });
  }
  else {
   [...tabs].forEach((tab) => {
     tab.classList.remove("scrollNav");
    });
  }
};

window.addEventListener("scroll", scrollFunc);

According to MDN, getElementsByClassName returns an "HTML Collection" https://developer.mozilla.org/en-US/docs/Web/API/HTMLCollection which on its own does not have a forEach method. You can use the spread syntax ... to add each item in the collection into a new array [] which does have a forEach method.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax

CodePudding user response:

document.getElementsByClassName returns a HTMLCollection. The classList attribute exists only on single elements. On the other hand, getElementById returns an element.

To change the class list of every element in the collection, you need to convert it into an array and then loop over every element in it. See below:

tabs = [...document.getElementsByClassName("navTabs")];

scrollFunc = function() {
  var y = window.scrollY;
  if (y >= 10) {
    tabs.forEach(tab => tab.classList.add("scrollNav"));
  }
  else {
    tabs.forEach(tab => tab.classList.remove("scrollNav"));
  }
};

window.addEventListener("scroll", scrollFunc);

This code uses ES6; you could easily convert it to a more browser-compatible version.

Related resources:

  • Related