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:
- HTMLCollection:
document.getElementsByClassName("navTabs")
- Singular Element:
document.getElementById("intro")
- Spread syntax:
[...document.getElementsByClassName("navTabs")]
- Arrow functions:
tab => tab.classList.add("scrollNav")