Closing dropdown button in Vanilla JS

Viewed 85

How do I close the dropdown button in Vanilla JS? I currently have a method to open the dropdown button but no way in which the close the button. I would like to keep the for loop in place but am unsure as to how to achieve the close. What is the proper way to handle the problem? Help would be appreciated. HTML

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
    <script
  src="https://code.jquery.com/jquery-3.6.0.js"
  integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk="
  crossorigin="anonymous"></script>
    <script src="https://kit.fontawesome.com/36947df53d.js" crossorigin="anonymous"></script>
    <link rel="stylesheet" type="text/css" href="style.css" />
  </head>
  <body>
  <div class="logo">
    <p id="logo">Logo</p>
    <button id="btn"><i class="fa-solid fa-bars fa-2xl"></i></button>
  </div>
   <nav class ="">
     <ul class ="">
       <li><a href="#" class="link">Link 1</a></li>
       <li><a href="#" class="link">Link 2</a></li>
       <li><a href="#" class="link">Link 3</a></li>
     </ul>
   </nav>
    <script src="script.js"></script>
  </body>
</html>

JS

let btnn = document.getElementById("btn");
btnn.addEventListener("click", changeBtn);

function changeBtn() { 
    let links = document.getElementsByClassName('link');
    for (let i = 0; i < links.length; i++) {
        document.getElementsByClassName('link')[i].style.display = "block";
    } 
}

CSS


body {
    height: 100vh;
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

.logo {
    display: block;
    text-align: left;
    background: red;
    height: 10vh;
}

.logo #logo {
    display: inline;
    line-height: 10vh;
    font-size: 3em;
    margin-left: 0.8em;
    
}

button#btn {
    display: inline;
    float: right;
    margin-right: 2em;
    line-height: 10vh;
    margin-top: 0;
    margin-bottom: 0;
    border: none;
    background-color: red;
    padding: 0;
}

nav {
    display: block;
    background-color: black;
    width: 100vw;
}

nav ul {
    display: block;
    list-style-type: none;
    margin: 0;
    padding-left: 0;
}

nav ul li {
    text-align: center; 
}

.link {
    display: none;
    color: white;
    font-size: 2.4em;
    background-color: blue;
    text-decoration: none;
    width: 100vw;
    height: 7vh;
    line-height: 7vh;
    border-bottom: 2px solid black;
    text-align: center;
}
3 Answers

You just need to add one function for the close button in javascript where the display is set to none on clicking the button again. You can do the same by clicking anywhere by window object.


Below is the code after the correction of the javascript part for closing the menu after clicking the button again. Hope you understand well. Please upvote if you like.

let btnn = document.getElementById("btn");
btnn.addEventListener("click", changeBtn);

function changeBtn() {
    let links = document.getElementsByClassName('link');
    for (let i = 0; i < links.length; i++) {
        document.getElementsByClassName('link')[i].style.display = "block";
    }
    // close the menu after clicking again
    btnn.removeEventListener("click", changeBtn);
    btnn.addEventListener("click", closeBtn);
}

function closeBtn() {
    let links = document.getElementsByClassName('link');
    for (let i = 0; i < links.length; i++) {
        document.getElementsByClassName('link')[i].style.display = "none";
    }
    // open the menu after clicking again
    btnn.removeEventListener("click", closeBtn);
    btnn.addEventListener("click", changeBtn);
}
body {
  height: 100vh;
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.logo {
  display: block;
  text-align: left;
  background: red;
  height: 10vh;
}

.logo #logo {
  display: inline;
  line-height: 10vh;
  font-size: 3em;
  margin-left: 0.8em;
}

button#btn {
  display: inline;
  float: right;
  margin-right: 2em;
  line-height: 10vh;
  margin-top: 0;
  margin-bottom: 0;
  border: none;
  background-color: red;
  padding: 0;
}

nav {
  display: block;
  background-color: black;
  width: 100vw;
}

nav ul {
  display: block;
  list-style-type: none;
  margin: 0;
  padding-left: 0;
}

nav ul li {
  text-align: center;
}

.link {
  display: none;
  color: white;
  font-size: 2.4em;
  background-color: blue;
  text-decoration: none;
  width: 100vw;
  height: 7vh;
  line-height: 7vh;
  border-bottom: 2px solid black;
  text-align: center;
}
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
    <script
      src="https://code.jquery.com/jquery-3.6.0.js"
      integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk="
      crossorigin="anonymous"
    ></script>
    <script
      src="https://kit.fontawesome.com/36947df53d.js"
      crossorigin="anonymous"
    ></script>
    <link rel="stylesheet" type="text/css" href="style.css" />
  </head>
  <body>
    <div class="logo">
      <p id="logo">Logo</p>
      <button id="btn"><i class="fa-solid fa-bars fa-2xl"></i></button>
    </div>
    <nav class="">
      <ul class="">
        <li><a href="#" class="link">Link 1</a></li>
        <li><a href="#" class="link">Link 2</a></li>
        <li><a href="#" class="link">Link 3</a></li>
      </ul>
    </nav>
    <script src="script.js"></script>
  </body>
</html>


You can use a simple classList.toggle function in JS by assigning a base class and then a "visible" class and just toggle between the two on click. See: https://www.w3schools.com/howto/howto_js_toggle_class.asp

Edit: added in the forEach just in case you wanted multiple buttons

let btnn = document.querySelectorAll(".btn");
btnn.forEach(btnn => btnn.addEventListener('click', function() {
  let links = document.getElementById('links');
  links.classList.toggle("visible");
}))
body {
  height: 100vh;
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.logo {
  display: block;
  text-align: left;
  background: red;
  height: 10vh;
}

.logo #logo {
  display: inline;
  line-height: 10vh;
  font-size: 3em;
  margin-left: 0.8em;
}

button#btn {
  display: inline;
  float: right;
  margin-right: 2em;
  line-height: 10vh;
  margin-top: 0;
  margin-bottom: 0;
  border: none;
  background-color: red;
  padding: 0;
}

nav {
  display: block;
  background-color: black;
  width: 100vw;
}

nav ul {
  display: block;
  list-style-type: none;
  margin: 0;
  padding-left: 0;
}

nav ul li {
  text-align: center;
}

.link {
  display: block;
  color: white;
  font-size: 2.4em;
  background-color: blue;
  text-decoration: none;
  width: 100vw;
  height: 7vh;
  line-height: 7vh;
  border-bottom: 2px solid black;
  text-align: center;
}

.links {
  display: none;
}

.links.visible {
  display: block;
}
<!DOCTYPE html>
<html>

<head>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
  <script src="https://code.jquery.com/jquery-3.6.0.js" integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" crossorigin="anonymous"></script>
  <script src="https://kit.fontawesome.com/36947df53d.js" crossorigin="anonymous"></script>
  <link rel="stylesheet" type="text/css" href="style.css" />
</head>

<body>
  <div class="logo">
    <p id="logo">Logo</p>
    <button class="btn" id="btn"><i class="fa-solid fa-bars fa-2xl"></i></button>
  </div>
  <nav class="">
    <ul class="links" id="links">
      <li><a href="#" class="link">Link 1</a></li>
      <li><a href="#" class="link">Link 2</a></li>
      <li><a href="#" class="link">Link 3</a></li>
    </ul>
  </nav>
  <script src="script.js"></script>
</body>

</html>

A more simple approach would be to add a class to the nav element and then toggle the visibility of nav element using the changeBtn function

I have highlighted the changes to the code using comments

let btnn = document.getElementById("btn");
btnn.addEventListener("click", changeBtn);

function changeBtn() { //changes to function

  let main_nav = document.getElementById("main_nav");

  if (main_nav.classList.contains("nav_active")) {
    //when element has nav_active class, hide the nav element and remove
    //the "nav-active" class

    main_nav.style.display = "none";
    main_nav.classList.remove("nav_active");
  } else {
    //when element doesn't have nav_active class, show the nav element
    //and add the "nav-active" class
    main_nav.style.display = "block";
    main_nav.classList.add("nav_active");
  }
}
body {
  height: 100vh;
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.logo {
  display: block;
  text-align: left;
  background: red;
  height: 10vh;
}

.logo #logo {
  display: inline;
  line-height: 10vh;
  font-size: 3em;
  margin-left: 0.8em;
}

button#btn {
  display: inline;
  float: right;
  margin-right: 2em;
  line-height: 10vh;
  margin-top: 0;
  margin-bottom: 0;
  border: none;
  background-color: red;
  padding: 0;
}

nav {
  display: none;
  background-color: black;
  width: 100vw;
}

nav ul {
  display: block;
  list-style-type: none;
  margin: 0;
  padding-left: 0;
}

nav ul li {
  text-align: center;
}

.link {
  display: block;
  /* Changed display: none to display: block */
  color: white;
  font-size: 2.4em;
  background-color: blue;
  text-decoration: none;
  width: 100vw;
  height: 7vh;
  line-height: 7vh;
  border-bottom: 2px solid black;
  text-align: center;
}
<script src="https://kit.fontawesome.com/36947df53d.js" crossorigin="anonymous"></script>

<div class="logo">
  <p id="logo">Logo</p>
  <button id="btn"><i class="fa-solid fa-bars fa-2xl"></i></button>
</div>
<nav id="main_nav" class="">
  <!-- added id to nav element -->
  <ul class="">
    <li><a href="#" class="link">Link 1</a></li>
    <li><a href="#" class="link">Link 2</a></li>
    <li><a href="#" class="link">Link 3</a></li>
  </ul>
</nav>

Related