I'm trying to add a className
on scroll. I keep getting a
document is undefined
edit: I found out I was getting the error from the typo. When I define document.getElementsByClassName("main-nav").scrollTop
nothing comes up in the console
. As well as the page does not get affected.
window.onscroll = function() {
windowScroll();
};
function windowScroll() {
if (document.getElementsByClassName("main-nav").scrollTop > 50 || document.documentElement.scrollTop > 50) {
document.getElementsByClassName("main-nav").className = "test";
} else {
document.getElementsByClassName("main-nav").className = "";
}
}
CSS is
.test {
background: pink
}
I'm not necessarily looking for the answer, I just want guidance
There are 2 problems:
getElementsByClassName
returns an array of HTMLCollection
and it has no property scrollTop
. You probably want the first item so the code shoul be document.getElementsByClassName("main-nav")[0]
(or document.querySelector(".main-nav")
)
But if you try it, you will get an error:
Cannot read property 'scrollTop' of undefined
window.onscroll = function() {
windowScroll();
};
function windowScroll() {
if (document.getElementsByClassName("main-nav").scrollTop > 50 || document.documentElement.scrollTop > 50) {
document.getElementsByClassName("main-nav").className = "test";
} else {
document.getElementsByClassName("main-nav").className = "";
}
}
html, body {
height: 150%;
}
.test {
background: pink
}
<div class="main-nav"></div>
The reason is that you override the class
attribute of .main-nav
by this assignment:
document.getElementsByClassName("main-nav").className = "";
In this line you set the class
attribute to empty string. You probably want to add / remove the test call but keeping the main-nav
class.
There are 2 things you can do:
id
attribute to main-nav
instead of the class
attribute, then use document.getElementById
method.window.onscroll = function() {
windowScroll();
};
function windowScroll() {
if (document.getElementById("main-nav").scrollTop > 50 || document.documentElement.scrollTop > 50) {
document.getElementById("main-nav").className = "test";
} else {
document.getElementById("main-nav").className = "";
}
}
html, body {
height: 150%;
}
#main-nav {
position: fixed;
width: 100%;
}
.test {
background: pink
}
<div id="main-nav">Main Nav</div>
test
class using classList.toggle
.window.onscroll = function() {
windowScroll();
};
function windowScroll() {
if (document.getElementsByClassName("main-nav")[0].scrollTop > 50 || document.documentElement.scrollTop > 50) {
document.getElementsByClassName("main-nav")[0].classList.add("test");
} else {
document.getElementsByClassName("main-nav")[0].classList.remove("test");
}
}
html, body {
height: 150%;
}
.main-nav {
position: fixed;
width: 100%;
}
.test {
background: pink
}
<div class="main-nav">Main Nav</div>
The final approach with some optimisations:
var mainNav = document.querySelector('.main-nav');
window.onscroll = function() {
windowScroll();
};
function windowScroll() {
mainNav.classList.toggle("test", mainNav.scrollTop > 50 || document.documentElement.scrollTop > 50);
}
html, body {
height: 150%;
}
.main-nav {
position: fixed;
width: 100%;
}
.test {
background: pink
}
<div class="main-nav">Main Nav</div>
The changes:
.main-nav
element on the global context (the window
object). It will not change so you don't need to find it in any scroll.querySelector
so you will get a single DOM element, not collection.classList.toggle
to toggle the class by condition.