Search code examples
javascripthtmlcssdropdownhtml-select

how to make a selection in a dropdown button?


I have coded a dropdown button with the below code. I have 2 issues I need help with please:

  1. I cant figure out why the dropdown box wont disappear when I click outside of the box? what code am i missing?

  2. what do I need to add to the links of the dropdown content to enable the dropdown content to be selectable options? so that you can click one options and it stays in that box as a selection?

/* When the user clicks on the button, 
    toggle between hiding and showing the dropdown content */
function myFunction() {
  document.getElementById("myDropdown").classList.toggle("show");
}

// Close the dropdown if the user clicks outside of it
window.onclick = function(event) {
  if (!event.target.matches('.dropbtn')) {
    var dropdowns = document.getElementsByClassName("dropdown-content");
    var i;
    for (i = 0; i < dropdowns.length; i++) {
      var openDropdown = dropdowns[i];
      if (openDropdown.classList.contains('show')) {
        openDropdown.classList.remove('show');
      }
    }
  }
}
.dropdown {
  position: relative;
  display: inline-block;
}

.dropbtn {
  background-color: #ffffff;
  color: black;
  padding: 10px 20px 10px 20px;
  font-size: 15px;
  border: none;
  cursor: pointer;
  border-radius: 5px;
  box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
}

.dropbtn:hover {
  background-color: #ffffff;
  color: black;
  padding: 10px 20px 10px 20px;
  font-size: 15px;
  border: none;
  cursor: pointer;
  border-radius: 5px;
  box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
 }

.dropbtn:focus {
  background-color: #ffffff;
  color: black;
  padding: 10px 20px 10px 20px;
  font-size: 15px;
  border: none;
  cursor: pointer;
  border-radius: 5px;
  box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
 }
 
.dropdown-content {
  display: none;
  position: absolute;
  background-color: #ffffff;
  min-width: 160px;
  box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
  z-index: 1;
  border-radius: 10px;
}

.dropdown-content a {
  color: black;
  font-family: helvetica;
  font-size: 14px;
  padding: 10px 16px;
  text-decoration: none;
  display: block;
}

.dropdown-content a:hover {background-color: #25362B; color: white; border-radius: 10px}

.dropdown:hover .dropdown-content {
  display: block;
}

.dropdown:hover .dropbtn {
  background-color: #ffffff;
}


#myDropdown > div {
 display: none
}
#myDropdown.show > div {
 display: block
}
<div class="dropdown">
  <button onclick="myFunction()" class="dropbtn">NIGHTS</button>
  <div id="myDropdown">
    <div class="dropdown-content">
      <a href="#">1 NIGHT</a>
      <a href="#">2 NIGHTS</a>
      <a href="#">3 NIGHTS</a>
      <a href="#">4 NIGHTS</a>
      <a href="#">5 NIGHTS</a>
      <a href="#">6 NIGHTS</a>
      <a href="#">7 NIGHTS</a>
      <a href="#">8 NIGHTS</a>
    </div>
  </div>
</div>


Solution

  • There's two main problems here:

    • You are attaching your global click handler to the window. That will give you unexpected results. Try using document.addEventListener instead.
    • The element you are toggling when you check against the event.target.matches is not the same element you toggled when clicking the menu button.
    document.addEventListener("click", function(event) {
      
      if (!event.target.matches('.dropbtn')) {
        
      // your code here
    
      }
    })
    
    

    Here is a full snippet based on your code: https://codepen.io/29b6/pen/eYVyjjV

    However. You should think about whether this is the best approach. "Rolling your own dropdown" seems simple at first but you need to consider accessibility. Can you navigate this with a keyboard, for instance? In 99% of cases you will be much safer using a native <select> :)

    EDIT: Updated the snippet to show how to handle "saving" the selected value.