bfoley_teamug
bfoley_teamug

Reputation: 79

How to close dropdown menu when user clicks

I am working on navigation with a clickable dropdown menu. The dropdown uses an input tag. Where I'm getting stuck is that I need the dropdown to close if the visitor clicks somewhere else on the page. I'm trying to use a target property, matches() method, and an onclick event.

What I notice in the console is that when I open the dropdown, both conditional statements appear and the dropdown doesn't open. It's as though the dropdown opens and closes at the same time.

What am I doing wrong and how do I get this to function correctly so that a user can simply open the dropdown menu and have it close when they click somewhere else on the webpage?

Thanks in advance! Below is the code. Here is the codepen: https://codepen.io/bfoley650/pen/NWxeXRB?editors=1111

HTML

<div class="dropdown">
    <input id="checkId" type="checkbox" name="menu" />
    <label for="checkId">
         <span class="heyhey">⋮</span>
    </label> 
    <div class="dropdown-content">
      <ul class="heyheyhey">
      <li><a href="#">Item 1</a></li>
      <li><a href="#">Item 2</a></li>
      <li><a href="#">Item 3</a></li>
        <li><a href="#">Item 4</a></li>
 
      </ul>
    </div>  
</div>

CSS

span {
  color: black;
  font-size: 24px;
  margin: 0 15px;
}

li {
  list-style-type: none;
}

.dropdown {
  float: left;
  overflow: hidden;
  font-size: 17px;
  border: none; 
  outline: none; 
  color: white;
  background-color: inherit;
  font-family: inherit; 
  margin: 10px 0; 
}
 
.dropdown-content {
  display: none;
  position: absolute;
  min-width: 160px;
  box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
  z-index: 1;
}

.dropdown-content a {
  float: none;
  color: black;
  padding: 12px 20px 12px 0;
  text-decoration: none;
  display: block;
  text-align: left;
}

input {
  display: none;
}

label {
  position: relative;
  cursor: pointer;
}


input:checked~.dropdown-content {
  display: block;
}

JS

let el = document.querySelector(".dropdown-content"); 

window.onclick = function(e) {
      if (e.target.matches(".heyhey")) {
        console.log("You clicked the dropdown menu");
      } else {
        console.log("You clicked somewhere else");
        el.style.display = "none";
      }
    } 

Upvotes: 0

Views: 1367

Answers (2)

Giga
Giga

Reputation: 31

I think you should move the span above the label:

<span class="heyhey">⋮</span>
<label for="checkId">
    <input id="checkId" type="checkbox" name="menu" />
</label> 

and add the following code to your conditional:

console.log("You clicked the dropdown menu");
el.style.display = "block";

Upvotes: 0

Elias Schablowski
Elias Schablowski

Reputation: 2812

The code:

window.onclick = function(e) {
    if (e.target.matches(".heyhey")) {
        console.log("You clicked the dropdown menu");
        el.style.display = "block"; // Shows the element
        e.preventDefault(); // Prevents propagation
    } else {
        console.log("You clicked somewhere else");
        el.style.display = "none";
    }
}

.preventDefault

event.preventDefault stops propagation, JS by default calls onclick for parent elements, this stops the double counting of your onclick handler.

el.style.display = "block";

This changes the display style from none, thus showing the element. This could be changed to any other display style except none.

Upvotes: 1

Related Questions