Home > Enterprise >  Dropdown menu not showing after clicking the icon (HTML)
Dropdown menu not showing after clicking the icon (HTML)

Time:07-21

I made a dropdown menu in my header, and when I click the moon icon (at the top right), the dropdown list doesn't show up but the function does get called when I click the icon. I've tried to use buttons but then clicking on the icon doesn't work. Any one help me with this? I am new to this thanks.

Html:

<li>
    <div >
        <script src="./assets/js/Dropdown.js"></script>
        <i   onclick="Dropdown()"></i>
        <div id="myDropdown" >
            <a><i ></i>  Dark Mode</a>
            <a><i ></i>  Light Mode</a>
            <a><i ></i>  System</a>
        </div>
     </div>
</li>

CSS:

.dropbtn {
    background-color: #24252A;
    color: white;
    padding: 16px;
    font-size: 16px;
    border: none;
    cursor: pointer;
}

.dropdown {
    position: relative;
    display: inline-block;
}

.dropdown-content {
    display: none;
    position: absolute;
    background-color: #f1f1f1;
    min-width: 160px;
    box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
    z-index: 1;
    cursor: pointer;
}

.dropdown-content a {
    color: black;
    padding: 12px 16px;
    text-decoration: none;
    display: block;
}
  
.dropdown-content a:hover {
    background-color: #ddd;
}

.show {
    display: block;
}

Javascript:

function Dropdown() {
    document.getElementById("myDropdown").classList.toggle("show");
}

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');
        }
      }
    }
}

CodePudding user response:

I used to have that problem. But, you don't have to reinvent the wheel, I recommend using a CSS framework, like Materialize or Bootstrap.

I recommend Materialize, it's easy to use and you just have to initialize each element you want to use.

I show you an example of navbar:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Example</title>
    <!-- Google icons -->
      <link href="https://fonts.googleapis.com/icon?family=Material Icons" rel="stylesheet">

    <!-- Compiled and minified CSS -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
</head>

<body>

    <nav>
        <div >
            <a href="#!" >Logo</a>
            <a href="#" data-target="mobile-demo" ><i >menu</i></a>
            <ul >
                <li><a href="sass.html">Sass</a></li>
                <li><a href="badges.html">Components</a></li>
                <li><a href="collapsible.html">Javascript</a></li>
                <li><a href="mobile.html">Mobile</a></li>
            </ul>
        </div>
    </nav>

    <ul  id="mobile-demo">
        <li><a href="sass.html">Sass</a></li>
        <li><a href="badges.html">Components</a></li>
        <li><a href="collapsible.html">Javascript</a></li>
        <li><a href="mobile.html">Mobile</a></li>
    </ul>

    <!-- Compiled and minified JavaScript -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
    
    <!-- Materialize initializers -->
    <script>
      document.addEventListener('DOMContentLoaded', function() {
    var elems = document.querySelectorAll('.sidenav');
    var instances = M.Sidenav.init(elems);
  });</script>
</body>

</html>

CodePudding user response:

You have two class attributes in your icon element.

When the user clicks the icon there are two click events - the first happens on the icon itself and the show class is correctly added.

The second is the general click on the window. Having two classes confuses the JS matches function which reckons the element does not match (ie would not get selected with .dropbtn) [probably not exactly 'confused' it just looks at the first class attribute so misses the dropbtn value] so it clears the show class.

If you put all the icon's classes into one attribute value then things work OK.

function Dropdown() {
  document.getElementById("myDropdown").classList.toggle("show");
}

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');
      }
    }
  }
}
.dropbtn {
  background-color: #24252A;
  color: white;
  padding: 16px;
  font-size: 16px;
  border: none;
  cursor: pointer;
}

.dropdown {
  position: relative;
  display: inline-block;
}

.dropdown-content {
  display: none;
  position: absolute;
  background-color: #f1f1f1;
  min-width: 160px;
  box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
  z-index: 1;
  cursor: pointer;
}

.dropdown-content a {
  color: black;
  padding: 12px 16px;
  text-decoration: none;
  display: block;
}

.dropdown-content a:hover {
  background-color: #ddd;
}

.show {
  display: block;
}
<li>
  <div >
    <script src="./assets/js/Dropdown.js"></script>
    <i  onclick="Dropdown()">click me</i>
    <div id="myDropdown" >
      <a><i ></i>  Dark Mode</a>
      <a><i ></i>  Light Mode</a>
      <a><i ></i>  System</a>
    </div>
  </div>
</li>

You could instead consider using event.stopPropagation in the first event handler which would stop the click event going through to the whole window.

  • Related