skip to Main Content

I want to be able to display a dropdown list whenever I click on dropdown but it does not seem to be working. When I use my browser developer tools. It shows the class active is being added to dropdown list yet it does not display. Here is my html, css and javascript code.

const dropdown = document.querySelectorAll(".dropdown");

dropdown.forEach(dropdown => {
  dropdown.addEventListener('click', () => {
    const dropdownList = dropdown.nextElementSibling;
    dropdownList.classList.toggle('active');
  });
});
:root {
  --font: 'Poppins', sans-serif;
  --primary-color: rgb(4, 228, 202);
  --dark: rgb(0, 24, 21);
  --faint: rgb(215, 255, 250);
  --grayish: rgb(155, 171, 169);
  --neutral-light: #fff;
  --neutral-dark: #000;
}

body {
  font-family: var(--font);
}

a {
  text-decoration: none;
  color: inherit;
}

nav {
  background-color: var(--dark);
  display: flex;
  justify-content: center;
  align-items: center;
}

nav ul {
  list-style: none;
}

nav ul li {
  display: inline-block;
  padding: 1rem;
  margin: 0;
}

nav ul li a {
  display: inline;
  color: var(--neutral-light);
  transition: 0.3s ease-in;
}

nav ul li a:hover {
  color: var(--primary-color);
}

nav ul li .dropdown {
  position: relative;
}

nav ul li .dropdown-list {
  position: absolute;
  box-shadow: 2px 2px 20px 10px rgba(0, 0, 0, 0.3);
  background-color: var(--neutral-light);
  z-index: 1;
  display: none;
}

nav ul li .dropdown-list a {
  display: inline-block;
  padding: .5rem 1rem;
  color: var(--dark);
  transition: 0.3s ease-in;
}

.active {
  display: block;
}
<nav>
  <ul id="menu">
    <li><a href="#">Home</a></li>

    <li>
      <a href="#" class="dropdown">About Us</a>

      <div class="dropdown-list">
        <a href="#">Who We Are</a>
        <a href="#">What We Do</a>
        <a href="#">Our Policies</a>
        <a href="#">FAQ</a>
    </li>
    <li>
      <a href="#" class="dropdown">Services</a>

      <div class="dropdown-list">
        <a href="#">IT Consultancy</a>
        <a href="#">Sofware Development</a>
        <a href="#">Website Designing</a>
        <a href="#">Graphics and Game Design</a>
        <a href="#">Research</a>
      </div>
    </li>

    <li><a href="#">Team</a></li>
    <li><a href="#">Contact Us</a></li>
  </ul>
</nav>

If I try to add the class dropdown to the li tag, the code works but if I add the dropdown class to the a tag inside the li tag it fails. What could be the problem with my code?

2

Answers


  1. The problem is with your .active style. Make it more specific:

    nav ul li .dropdown-list.active {display: block}
    
    Login or Signup to reply.
  2. CSS and specificity

    While the class is applied, its style display: block is not. This is due to specificity:

    The rule that declares display: none has the selector list nav ul li .dropdown-list: 1 class selector and 3 type selectors, i.e. a specificity of 0-1-3. (The 0 stands for "0 ID-selectors".)

    The rule that declares display: block has the selector ‘list’ .active: Only 1 class selector, i.e. a specificity of 0-1-0, which is less specific than 0-1-3.

    The declarations of more specific rules apply, which is why display: block is overridden with display: none.

    For the rule declaring display: block, try to increase the specificity. For example, use a similar selector list but with the additional selector .active: nav ul li .dropdown-list.active.


    Enabling selectors, not disabling ones

    Instead of increasing the specificity, you can also hide the element conditionally instead of by default. Some call these "Enabling CSS selectors".

    Basically, instead of reverting or overriding styles, try to only apply styles when necessary.

    In your case, you may change your CSS from:

    .dropdown-list {
      /* ... (default styles) */
      display: none;
    }
    
    .dropdown-list.active {
      display: block;
    }
    

    To use selectors like this:

    .dropdown-list {
      /* ... (default styles) */
    }
    
    .dropdown-list:not(.active) {
      display: none;
    }
    

    Note: You may still run into specificity issues with this approach. This approach mostly helps with multiple rules trying to override the same property, as even with the same specificity, only certain rules apply due to the used selectors.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search