0

So I am creating a responsive navbar.

nav bar when on big screen

When a user is using a phone or minimizes the browser, A hamburger icon should appear like so:

navbar hamburger So I created a js function that whenever a user clicks on the icon, he/she should see all the links available. but when I check the console in my browser, it says that addEventListener is null. I don't think I have defined my function wrong and have check the docs again to see if I write the code wrongly but it's not that.

HTML

 <nav class="navbar">
            <span class="navbar-toggle" id="js-navbar-toggle">
                <i class="fas fa-bars"></i>
            </span>
            <a href="#" class="logo">logo</a>
            <ul class="main-nav" id="js-menu">
                <li>
                    <a href="#" class="nav-links">Home</a>
                </li>
                <li>
                    <a href="#" class="nav-links">Products</a>
                </li>
                <li>
                    <a href="#" class="nav-links">About Us</a>
                </li>
                <li>
                    <a href="#" class="nav-links">Contact Us</a>
                </li>
                <li>
                    <a href="#" class="nav-links">Blog</a>
                </li>
            </ul>
    </nav>

CSS

    * {
    box-sizing: border-box;
    padding: 0;
    margin: 0;
}

body {
    font-family: 'Josefin Sans', sans-serif;
}

.navbar {
    font-size: 18px;
    background-image: linear-gradient(260deg, #2376ae 0%, #c16ecf 100%);
    border: 1px solid rgba(0, 0, 0, 0.2);
    padding-bottom: 10px;
}

.main-nav {
    list-style-type: none;
    display: none;
}

.nav-links,
.logo {
    text-decoration: none;
    color: rgba(255, 255, 255, 0.7);
}

.main-nav li {
    text-align: center;
    margin: 15px auto;
}

.logo {
    display: inline-block;
    font-size: 22px;
    margin-top: 10px;
    margin-left: 20px;
}

.navbar-toggle {
    position: absolute;
    top: 10px;
    right: 20px;
    cursor: pointer;
    color: rgba(255, 255, 255, 0.8);
    font-size: 24px;
}

.active {
    display: block;
}

@media screen and (min-width: 768px) {
    .navbar {
        display: flex;
        justify-content: space-between;
        padding-bottom: 0;
        height: 70px;
        align-items: center;
    }

    .main-nav {
        display: flex;
        margin-right: 30px;
        flex-direction: row;
        justify-content: flex-end;
    }

    .main-nav li {
        margin: 0;
    }

    .nav-links {
        margin-left: 40px;
    }

    .logo {
        margin-top: 0;
    }

    .navbar-toggle {
        display: none;
    }

    .logo:hover,
    .nav-links:hover {
        color: rgba(255, 255, 255, 1);


  }
}

and JS:

let mainNav = document.getElementById('js-menu');
let navBarToggle = document.getElementById('js-navbar-toggle');

navBarToggle.addEventListener('click', function () {
  mainNav.classList.toggle('active');
});

It is saying Uncaught TypeError: Cannot read property 'addEventListener' of null

The expected result should make the links appear when the hamburger icon is clicked.

bradrar
  • 647
  • 1
  • 8
  • 19
  • 1
    navbarToggle is null, not addEventListener - the message says you're trying to access "a property of something that's a null", not "a null property of something". It's a bit deceptive. Anyway: your problem is that the DOM doesn't contain the element you're looking for (by id) when you're looking for it. – dkellner Dec 29 '18 at 13:51
  • That's odd, I added the id="js-navbar-toggle" in my html. Why is that? – bradrar Dec 29 '18 at 14:08
  • 1
    You have `.navbar-toggle {display: none; }` You can not click a display none element – enxaneta Dec 29 '18 at 14:12
  • Okay thank you for that. I am following this guide [here](https://itnext.io/how-to-build-a-responsive-navbar-using-flexbox-and-javascript-eb0af24f19bf) . Maybe this guide is wrong. I will figure something else. Thank you again. – bradrar Dec 29 '18 at 14:16
  • 1
    @bradrar Because at that moment when you're looking for it, the html is not yet parsed. JavaScript that interacts with DOM should always run only after the DOM is ready. There are a number of ways to achieve that. The most trivial of them is to put the js after the html part it refers to; domReady techniques are reliable too, and if nothing helps, you can add extra delays so that the browser has the time to render. But if document.getElementById returns null for something, it's not there. That much is certain. – dkellner Dec 30 '18 at 01:28
  • 1
    @dkellner Thank you for this. after you said this, I check my html file and realized that the script tag is on the `head`, Now it's below all my element before the ending `

    ` it works now. Thank you

    – bradrar Dec 31 '18 at 10:50

1 Answers1

2

Try adding your code inside document onload. when you are trying bind click event your dom is not yet ready, so that's why your navBarToggle is null.

document.onload = function(e){ 
   let mainNav = document.getElementById('js-menu');
   let navBarToggle = document.getElementById('js-navbar-toggle');

   navBarToggle.addEventListener('click', function () {
      mainNav.classList.toggle('active');
   });
}
Amit Chauhan
  • 6,151
  • 2
  • 24
  • 37
  • Okay, Thank you, I wonder why my dom is not ready? This is the first time it happens to me. Thanks again! – bradrar Dec 29 '18 at 14:03
  • 1
    browser is doing everything asynchronous i.e. loading dom, script, stylesheet external images etc. so at the time of javascript is loaded it's not guaranteed that dom is ready. – Amit Chauhan Dec 29 '18 at 14:14