Vanilla JS solution for closing dropdown button

Is there a way to close the dropdown button using Vanilla JS? I have successfully implemented a method to open the dropdown button, but am struggling to find a way to close it. I would like to maintain the for loop for functionality but need guidance on how to achieve the closing action. Any tips on handling this issue would be greatly 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;
}

Answer №1

To create functionality for the close button in JavaScript, simply add a function that sets the display property to "none" when the close button is clicked. You can achieve the same effect by clicking anywhere on the window.

Here is the updated JavaScript code for closing the menu after clicking the button again:

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>


Answer №2

A straightforward technique in JavaScript involves utilizing the classList.toggle function. Simply assign a base class and a "visible" class, then toggle between them with a click event. Check out: https://www.w3schools.com/howto/howto_js_toggle_class.asp

Edit: Also included a forEach loop for scenarios with multiple buttons

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

/* More CSS styles here */

.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>
  <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>

Answer №3

A simpler way to handle this is by assigning a class to the navigation element and then using the changeBtn function to toggle its visibility.

The modifications made to the code are marked with comments.

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

function changeBtn() { // Updated function

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

  if (main_nav.classList.contains("nav_active")) {
    // Hide the nav element and remove the "nav-active" class when it has the class
    main_nav.style.display = "none";
    main_nav.classList.remove("nav_active");
  } else {
    // Show the nav element and add the "nav-active" class when it doesn't have the 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>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Leveraging Multiple MongoDB Databases in Meteor.js

Can 2 Meteor.Collections fetch data from separate MongoDB database servers? Dogs = Meteor.Collection('dogs') // mongodb://192.168.1.123:27017/dogs Cats = Meteor.Collection('cats') // mongodb://192.168.1.124:27017/cats ...

Attempting to have this .js lightbox appear as soon as the page loads

This Lightbox is absolutely stunning! However, I am looking for a way to automatically trigger the lightbox when the page loads. ...

Is there a way to achieve a similar outcome on my site?

Recently, I noticed a mouse-hover effect on two websites and found it quite appealing. https://i.sstatic.net/Ly0gP.png https://i.sstatic.net/oDe1i.png This is the specific effect that caught my attention. Can anyone provide me with insight on how to impl ...

Challenges with jQuery's 'this' selector in conjunction with if/else conditions

I am currently working on a project that involves allowing users to modify or move an image in the browser by clicking on buttons located on the side of the page. However, I am facing issues with the script in my if/else statement. Here is a snippet of wha ...

Using ui-tabs with Ng-repeat to create both dynamic and static tabs

I'm currently working on creating a date tabs feature where users can click to add more tabs. Below is a snippet of the code I'm using: `<uib-tabset justified="true" class="ui-tab"> <uib-tab ng-repeat="date in dates track by $index" hea ...

Opera and Internet Explorer have trouble properly applying css text-decoration

It appears that the CSS text-decoration style is not being correctly displayed in Opera 11 and IE 9, but works perfectly fine in Chrome, Firefox, and Safari. Can anyone offer a solution to fix this issue? Incorrect Rendering: Correct Rendering: Below is ...

How can a JavaScript function be used to check a tag's status?

I currently have two select tags on my webpage. I want to ensure that only one option can be selected at a time from these two tags. If the user tries to select options from both tags, an error message should be displayed instructing them to choose only on ...

How to modify a specific property of an array object in JavaScript

I have an array of objects that looks like this: [ { number: 1, name: "A" }, { number: 2, name: "e", }, { number: 3, name: "EE", } ] I am looking for a way to insert an object into the array at a specific position and ...

Ways to dynamically add a JavaScript file into a webpage

In an attempt to dynamically load a JavaScript file, I utilized a div element with a specific class name to contain the verification script. The script is designed to check if the intended JavaScript file has been loaded and, if not, to generate a new ex ...

What is the solution to the error "Maximum update depth exceeded. Calls to setState inside componentWillUpdate or componentDidUpdate" in React?

Everything was running smoothly until this unexpected issue appeared. I attempted to change the condition to componentDidMount, but unfortunately, that didn't resolve the problem. The error is occurring in this particular function. componentDidUpd ...

development session not persisting on local server (localhost:4200)

Currently, I am utilizing angular for the frontend and node.js along with express for the backend of my application. The interesting observation is that when I run the app on localhost:3000 (the designated port for the express app), everything operates cor ...

The fragment shader must not declare any varyings with the same name but different type, or statically used varyings without being declared in the vertex shader. An example of this is

I'm struggling with shaders because I want the fog to be reflected in the water using Three.js sky_sun_shader. I added the following code snippet to the fragment Shader: THREE.ShaderChunk[ "fog_pars_fragment" ], THREE.ShaderChunk ["fog_fragment" ], ...

Checking URL validity with regular expressions in Vue JS

Currently, I am attempting to validate URL strings utilizing a regular expression. The following regex is what I am using for this purpose: var regex = /^(http|https):\/\/+[\www\d]+\.[\w]+(\/[\w\d]+)?/ With thi ...

Introduce an additional parameter to the Prestashop Cart entity

After setting up a radiobox "stock_action" in the Cart, I need to send its value to the Cart object for additional order costs. In the Cart Override, the $stock_action variable has been added: public $stock_action; /** * @see ObjectModel::$defi ...

CSS vertical alignment: Getting it just right

I am currently using Bootstrap and below is a snippet of the code I have implemented. <div class="row"> <div class="col-lg-6"><img src="#" alt=""></div> <div class="col-lg-6"> <h2>Heading</h2> ...

Obtaining your CSGO inventory via Steam API using jsonp: A step-by-step guide

Hey there! I'm currently facing an issue while trying to access a player's CSGO inventory using Valve's API. Unfortunately, I keep running into the error message stating that no 'access-control-allow-origin' header is present on th ...

Effective methods for synchronizing two dropdown menus with varied displays using React

Having a list of countries with specific key-value pairs, I am interested in creating two Dropdown lists. The first will display the keys, while the second will show the corresponding text values. The main objective is to provide the option to select eith ...

Ordering AngularJS by property name with spaces

While working with the MEAN stack and jade, I encountered an issue with AngularJS when using ng-repeat, ng-click, and orderby to sort columns in a table. Everything was working well until I tried sorting by a column named "To Do" which contains a space. Th ...

Converting a local Node.js server to an online server: A step-by-step guide

Currently working on a game for my school project. Originally designed to be an online multiplayer game, but have only been able to test it locally so far. Need help figuring out how to modify my server code to make it functional as a legitimate online ser ...

A method for retrieving the variables from the initial API function for use in a subsequent API function

$.getJSON(url, function (data) { $.getJSON(url_wind, function (data2) { //perform actions with 'data' and 'data2' }); }); While attempting to use the data from the initial getJSON() call in the second getJSON() call ...