So I'm trying to make my nav bar stick to the top of the page when people scroll, but it doesn't want to work. For some reason, the console keeps throwing an error saying the classList.remove()
attributes are undefined. Yet at the same time, when I remove them, the navbars don't stick.
If it helps, I built two navbars. One for mobile/tablet and another for desktops.
What's going on with this?
// ---------------------------------------- GLOBAL VARIABLES
const mobileNavbar = document.getElementsByClassName("mobile-navbar");
const desktopNavbar = document.getElementsByClassName("desktop-navbar");
const stickyDesktop = desktopNavbar.offsetTop;
const stickyMobile = mobileNavbar.offsetTop;
window.onscroll = function () {
stickyNav()
};
function stickyNav() {
if (window.pageYOffset >= stickyDesktop || window.pageYOffset >= stickyMobile) {
desktopNavbar.classList.add("sticky");
mobileNavbar.classList.add("sticky");
}
else {
desktopNavbar.classList.remove("sticky");
mobileNavbar.classList.remove("sticky");
}
}
// ---------------------------------------- DESKTOP NAVBAR
document.addEventListener('click', e => {
const isDropdownButton = e.target.matches("[data-dropdown-button]")
if (!isDropdownButton && e.target.closest('[data-dropdown]') != null) return
let currentDropdown
if (isDropdownButton) {
currentDropdown = e.target.closest('[data-dropdown]')
currentDropdown.classList.toggle('active')
}
document.querySelectorAll('[data-dropdown].active').forEach(dropdown => {
if (dropdown === currentDropdown) return
dropdown.classList.remove('active')
})
})
// ---------------------------------------- MOBILE NAVBAR
const toggleButton = document.getElementsByClassName('fa-bars')[0]
const mobileNavBar = document.getElementsByClassName('mobile-navbar-links')[0]
toggleButton.addEventListener('click', () => {
mobileNavBar.classList.toggle('active')
})
* {
box-sizing: border-box;
}
a {
text-decoration: none;
color: #000;
}
body {
margin: 0;
padding: 0;
}
html {
scroll-behavior: smooth;
}
.sticky {
position: fixed;
top: 0;
width: 100%;
}
.sticky + body {
padding-top: 60px;
}
.scrollDown {
position: absolute;
top: 93%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
}
.scrollDown a {
text-decoration: none;
}
.scrollDown p {
margin: 0;
font-family: 'Nunito', sans-serif;
font-size: 20px;
color: #fff;
}
.fa-chevron-down,
.fa-chevron-up {
width: 50px;
height: 50px;
font-size: 32px;
color: #fff;
;
}
.scrollDown:hover {
transition: .2s ease;
}
@media screen and (max-width: 600px) {
/* ------------------------------- MOBILE NAVBAR */
.desktop-navbar {
display: none;
}
.mobile-navbar {
display: flex;
overflow: hidden;
justify-content: space-between;
align-items: center;
background-color: #333;
color: #fff;
}
.mobile-brand-title {
font-size: 1.5rem;
margin: .5rem;
}
.mobile-navbar-links ul {
margin: 0;
padding: 0;
display: flex;
}
.mobile-navbar-links li {
list-style: none;
}
.mobile-navbar-links li a {
color: #fff;
padding: 1rem;
display: block;
}
.mobile-navbar-links li:hover {
background-color: #555;
}
.mobile-navbar .fa-bars {
position: absolute;
display: none;
flex-direction: column;
justify-content: space-between;
top: .75rem;
right: 1rem;
color: #fff;
width: 1rem;
height: 1rem;
cursor: pointer;
}
.mobile-navbar .fa-bars {
display: flex;
}
.mobile-navbar-links {
display: none;
width: 100%;
}
.mobile-navbar {
flex-direction: column;
align-items: flex-start;
}
.mobile-navbar-links ul {
width: 100%;
flex-direction: column;
}
.mobile-navbar-links li {
text-align: center;
}
.mobile-navbar-links.active {
display: flex;
}
}
@media screen and (min-width: 601px) {
/* ------------------------------- DESKTOP NAVBAR */
.mobile-navbar {
display: none;
}
.desktop-navbar {
background-color: #f3f3f3;
overflow: hidden;
display: flex;
align-items: baseline;
padding: .5rem;
gap: 1rem;
}
.link {
background: none;
border: none;
text-decoration: none;
color: #777;
font-family: inherit;
font-size: inherit;
cursor: pointer;
padding: 0;
}
.dropdown.active+.link,
.link:hover {
color: #000;
}
.dropdown {
position: relative;
}
.dropdown-menu {
position: absolute;
left: 0;
top: calc(100% + .25rem);
background-color: #fff;
padding: .75rem;
border-radius: .25rem;
box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.3);
z-index: 1000;
opacity: 0;
pointer-events: none;
transition: opacity 150ms ease, transform 150ms ease;
transform: translateY(-10px);
}
.dropdown.active>.link+.dropdown-menu {
opacity: 1;
transform: translateY(0px);
pointer-events: auto;
}
.information-grid {
display: grid;
grid-template-columns: repeat(2, max-content);
gap: 2rem;
}
.dropdown-links {
display: flex;
flex-direction: column;
gap: .25rem;
}
}
<!DOCTYPE html>
<html>
<head>
<title>Fox Bank</title>
<!-- Meta tags -->
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Links/Styles -->
<link rel="stylesheet" href="styles/styles.css">
<link rel="stylesheet" href="styles/normalize.css">
<link rel="stylesheet" href="styles/responsive.css">
<link rel="stylesheet" href="styles/flickity.min.css" media="screen">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Nunito&display=swap" rel="stylesheet">
<!-- Javascript -->
<script src="https://kit.fontawesome.com/8821130486.js" crossorigin="anonymous"></script>
<script src="js/jquery.js" defer></script>
<script src="js/app.js" async defer></script>
<script src="js/flickity.min.js" defer></script>
</head>
<body>
<!--------------------- DESKTOP NAVBAR -->
<!--------------------------------------->
<div class="desktop-navbar">
<div>
<a href="#">
<h1>Big Bank</h1>
</a>
</div>
<div class="dropdown" data-dropdown>
<button class="link" data-dropdown-button>About</button>
<div class="dropdown-menu information-grid">
<div>
<div class="dropdown-heading">Meet Our Team</div>
<div class="dropdown-links">
<a href="#" class="link">Staff</a>
<a href="#" class="link">Board of Directors</a>
</div>
</div>
<div>
<div class="dropdown-heading">Our History</div>
<div class="dropdown-links">
<a href="#" class="link">Overview</a>
<a href="#" class="link">Future</a>
</div>
</div>
<div>
<div class="dropdown-heading">Blog</div>
<div class="dropdown-links">
<a href="#" class="link">Latest Posts</a>
<a href="#" class="link">In The Community</a>
<a href="#" class="link">Security & Fraud Prevention</a>
<a href="#" class="link">National & International Money</a>
</div>
</div>
<div>
<div class="dropdown-heading">Contact Us</div>
<div class="dropdown-links">
<a href="#" class="link">Support Center</a>
<a href="#" class="link">Phone & Mailing Information</a>
<a href="#" class="link">Social Media</a>
</div>
</div>
</div>
</div>
<div class="dropdown" data-dropdown>
<button class="link" data-dropdown-button>Products</button>
<div class="dropdown-menu information-grid">
<div>
<div class="dropdown-heading">Checking</div>
<div class="dropdown-links">
<a href="#" class="link">Basic Checking</a>
<a href="#" class="link">Teens Checking</a>
<a href="#" class="link">Prime Checking</a>
<a href="#" class="link">Elite Checking</a>
</div>
</div>
<div>
<div class="dropdown-heading">Savings</div>
<div class="dropdown-links">
<a href="#" class="link">Basic Savings</a>
<a href="#" class="link">Teens Savings</a>
<a href="#" class="link">Prime Savings</a>
<a href="#" class="link">Elite Savings</a>
</div>
</div>
<div>
<div class="dropdown-heading">Borrow</div>
<div class="dropdown-links">
<a href="#" class="link">Personal Loans</a>
<a href="#" class="link">Auto Loans</a>
<a href="#" class="link">Credit Cards</a>
<a href="#" class="link">Mortgage</a>
<a href="#" class="link">Shark Loans</a>
</div>
</div>
<div>
<div class="dropdown-heading">Retirement</div>
<div class="dropdown-links">
<a href="#" class="link">Traditional IRA</a>
<a href="#" class="link">Roth IRA</a>
<a href="#" class="link">Self Employment IRA</a>
</div>
</div>
</div>
</div>
<a href="#"><button>Login</button></a>
</div>
<!---------------------- MOBILE NAVBAR -->
<!--------------------------------------->
<nav class="mobile-navbar">
<div class="mobile-brand-title">Fox Bank</div>
<i class="fa-solid fa-bars"></i>
<div class="mobile-navbar-links">
<ul>
<li><a href="#">About</a></li>
<li><a href="#">Products</a></li>
<li><a href="#">Login</a></li>
</ul>
</div>
</nav>
<div>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<p>CONTENT GOES HERE</p>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<p>CONTENT GOES HERE</p>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<p>CONTENT GOES HERE</p>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<p>CONTENT GOES HERE</p>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
</div>
</body>
</html>
The navbar variables contain node lists, not navigation bar elements, and hence don't have a classList
property.
Try replacing
const mobileNavbar = document.getElementsByClassName("mobile-navbar");
const desktopNavbar = document.getElementsByClassName("desktop-navbar");
with
const mobileNavbar = document.querySelector(".mobile-navbar");
const desktopNavbar = document.querySelector(".desktop-navbar");
or add [0]
to after node list values to select the first element in each list.