Home > Net >  How can I turn my navbar links into a dropdown menu with HTML CSS and JavaScript?
How can I turn my navbar links into a dropdown menu with HTML CSS and JavaScript?

Time:05-16

I am trying to turn the first two links of my navbar into dropdown menus. I want to make it so that when you click on them, the dropdown menu shows and the arrow icon turns from a downward pointing arrow to an upwards pointing one.

I have tried to use JavaScript to carry out the OnClick events but I have had no success.

For some reason as well, my two dropdown menus are overlapping each other and they are not positioned under the correct navbar links. One should be one appearing under the features link and the other under the company link in the navigation bar. I would also like to request help on how to fix this.

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

// Close the dropdown menu if the user clicks outside of it
window.onclick = function(event) {
  if (!event.target.matches('.dropdown-arrow')) {
    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');
      }
    }
  }
}
@import url('https://fonts.googleapis.com/css2?family=Epilogue:wght@500;700&display=swap');
* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
  font-family: 'Epilogue', 'sans-serif';
}

.body-container {
  background-color: hsl(0, 0%, 98%);
  height: 100vh;
  width: 100vw;
  max-width: 100%;
}

.navbar {
  display: flex;
  align-items: center;
}

.navbar-flex li {
  margin-right: auto;
  display: inline-block;
  padding: 1em;
}

.navbar-flex a {
  color: hsl(0, 0%, 41%);
  text-decoration: none;
}

.navbar-flex a:hover {
  color: hsl(0, 0%, 8%);
}

.navbar li {
  list-style-type: none;
}

.navbar img {
  padding: 1.5em 1em 1em 2em;
}

.navbar-btn {
  margin-left: auto;
  padding: 1.5em;
}

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

.dropdown-content {
  /*display: none;*/
  position: absolute;
  min-height: 100px;
  box-shadow: 0px 8px 16px 0px hsla(0, 0%, 0%, 0.2);
  z-index: 1;
}

.dropdown-content a {
  color: hsl(0, 0%, 8%);
  padding: 12px 16px;
  text-decoration: none;
  display: block;
}


/* Change color of dropdown links on hover */

.dropdown-content a:hover {
  background-color: hsl(0, 0%, 41%);
}

.dropdown-arrow {
  color: hsl(0, 0%, 41%);
  outline: none;
  background: none;
  border: none;
  cursor: pointer;
}

.dropdown-arrow:hover {
  color: hsl(0, 0%, 8%);
}

.dropdown-links {
  text-decoration: none;
  display: block;
  padding: 1em;
  color: hsl(0, 0%, 8%);
}

.dropdown-links:hover {
  background-color: hsl(0, 0%, 98%);
}

.show {
  display: block;
}


/* Styles for both buttons in the navbar */

.btn-primary {
  color: hsl(0, 0%, 41%);
  outline: none;
  padding: 0.5em;
  margin-left: 1em;
  cursor: pointer;
}

.btn-primary:hover {
  color: hsl(0, 0%, 8%);
}


/* Styles for login button in the navbar */

#login-btn {
  border: none;
  background: none;
}


/* Styles for register button in the navbar */

#register-btn {
  padding: 0.8em;
  border-radius: 10px;
  background: none;
  border-color: hsl(0, 0%, 41%);
  border-width: 1px;
}

.register-btn:hover {
  border-color: hsl(0, 0%, 8%);
}
<div >
  <nav >
    <a href="#"><img src="images/logo.svg" alt="company logo"></a>
    <ul >

      <li><a href="#">Features </a>
        <!-- Features dropdown menu-->
        <div >
          <button onclick="myFunction()" >
            <svg class = "drop-image" svg width="10" height="6" xmlns="http://www.w3.org/2000/svg"><path stroke="#686868" stroke-width="1.5" fill="none" d="m1 1 4 4 4-4"/></svg>
          </button>
          <ul >
            <li><a  href="#">Todo List</a></li>
            <li><a  href="#">Calendars</a></li>
            <li><a  href="#">Reminders</a></li>
            <li><a  href="#">Planning</a></li>
          </ul>
        </div>
      </li>

      <li><a href="#">Company </a>
        <!-- Company dropdown menu-->
        <div >
          <button onclick="myFunction()" >
            <svg class = "drop-image" width="10" height="6" xmlns="http://www.w3.org/2000/svg"><path stroke="#686868" stroke-width="1.5" fill="none" d="m1 1 4 4 4-4"/></svg>
          </button>
          <ul id="my-dropdown" >
            <li><a  href="#">History</a></li>
            <li><a  href="#">Our Team</a></li>
            <li><a  href="#">Blog</a></li>
          </ul>
        </div>
      </li>

      <li><a href="#">Careers</a></li>
      <li><a href="#">About</a></li>
    </ul>

    <div >
      <button  id="login-btn">Login</button>
      <button  id="register-btn">Register</button>
    </div>
  </nav>

</div>

</div>
</div>

CodePudding user response:

I wrote you a possible Vanilla JS approach to handle the behaviour you are looking for:

  1. First select all the li elements in your list;
  2. Add a click event listener;
  3. On each click it adds or remove the classes that show the modal and rotate the arrow, based on a property that I attach to the DOM node, isOpen, so you can always know if a certain element is visually opened or closed. This is useful if you plan to close the other opened dropdowns while opening a new one to prevent overlapping.

const links = document.querySelectorAll(".navbar-flex>li")
links.forEach((el, i) => {
  el.isOpen = false;
  el.onclick = e => {
    const dropdown = el.querySelector(".dropdown")
    const arrow = el.querySelector(".dropdown-arrow")
    el.isOpen ? close(dropdown,
      arrow) : open(dropdown,
      arrow)
    el.isOpen = !el.isOpen
    //Close other open dropdowns
    links.forEach((el, j) => {
      const dropdown = el.querySelector(".dropdown")
      const arrow = el.querySelector(".dropdown-arrow")
      if (i !== j) {
        if (el.isOpen) {
          close(dropdown, arrow)
          el.isOpen = false
        }
      }
    })
  }

})


function open(el, arrow) {
  el.classList.add("show")
  arrow.classList.add("rotate")
}

function close(el, arrow) {
  el.classList.remove("show")
  arrow.classList.remove("rotate")
}
@import url('https://fonts.googleapis.com/css2?family=Epilogue:wght@500;700&display=swap');
* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
  font-family: 'Epilogue', 'sans-serif';
}

.body-container {
  background-color: hsl(0, 0%, 98%);
  height: 100vh;
  width: 100vw;
  max-width: 100%;
}

.navbar {
  display: flex;
  align-items: center;
}

.navbar-flex li {
  margin-right: auto;
  display: inline-block;
  padding: 1em;
}

.navbar-flex a {
  color: hsl(0, 0%, 41%);
  text-decoration: none;
}

.navbar-flex a:hover {
  color: hsl(0, 0%, 8%);
}

.navbar li {
  list-style-type: none;
}

.navbar img {
  padding: 1.5em 1em 1em 2em;
}

.navbar-btn {
  margin-left: auto;
  padding: 1.5em;
}

.dropdown {
  position: absolute;
  display: none;
  background: #FFF;
}

.dropdown-content {
  min-height: 100px;
  box-shadow: 0px 8px 16px 0px hsla(0, 0%, 0%, 0.2);
  z-index: 1;
  display: flex;
  flex-direction: column;
}

.dropdown-content a {
  color: hsl(0, 0%, 8%);
  padding: 12px 16px;
  text-decoration: none;
  display: block;
}


/* Change color of dropdown links on hover */

.dropdown-content a:hover {
  background-color: hsl(0, 0%, 41%);
}

.dropdown-arrow {
  color: hsl(0, 0%, 41%);
  outline: none;
  background: none;
  border: none;
  cursor: pointer;
  transition: all 0.2s ease-out;
}

.dropdown-arrow:hover {
  color: hsl(0, 0%, 8%);
}

.dropdown-links {
  text-decoration: none;
  display: block;
  padding: 1em;
  color: hsl(0, 0%, 8%);
}

.dropdown-links:hover {
  background-color: hsl(0, 0%, 98%);
}

.show {
  display: block !important;
}

.rotate {
  transform: rotate(180deg);
}


/* Styles for both buttons in the navbar */

.btn-primary {
  color: hsl(0, 0%, 41%);
  outline: none;
  padding: 0.5em;
  margin-left: 1em;
  cursor: pointer;
}

.btn-primary:hover {
  color: hsl(0, 0%, 8%);
}


/* Styles for login button in the navbar */

#login-btn {
  border: none;
  background: none;
}


/* Styles for register button in the navbar */

#register-btn {
  padding: 0.8em;
  border-radius: 10px;
  background: none;
  border-color: hsl(0, 0%, 41%);
  border-width: 1px;
}

.register-btn:hover {
  border-color: hsl(0, 0%, 8%);
}
<div >
  <nav >
    <a href="#"><img src="images/logo.svg" alt="company logo"></a>
    <ul >

      <li>
        <a href="#">Features </a>
        <button >
            <svg class = "drop-image" svg width="10" height="6" xmlns="http://www.w3.org/2000/svg"><path stroke="#686868" stroke-width="1.5" fill="none" d="m1 1 4 4 4-4"/></svg>
          </button>
        <!-- Features dropdown menu-->
        <div >

          <ul >
            <li><a  href="#">Todo List</a></li>
            <li><a  href="#">Calendars</a></li>
            <li><a  href="#">Reminders</a></li>
            <li><a  href="#">Planning</a></li>
          </ul>
        </div>
      </li>

      <li>
        <a href="#">Company </a>
        <button >
            <svg class = "drop-image" width="10" height="6" xmlns="http://www.w3.org/2000/svg"><path stroke="#686868" stroke-width="1.5" fill="none" d="m1 1 4 4 4-4"/></svg>
          </button>
        <!-- Company dropdown menu-->
        <div >
          <ul id="my-dropdown" >
            <li><a  href="#">History</a></li>
            <li><a  href="#">Our Team</a></li>
            <li><a  href="#">Blog</a></li>
          </ul>
        </div>
      </li>

      <li><a href="#">Careers</a></li>
      <li><a href="#">About</a></li>
    </ul>

    <div >
      <button  id="login-btn">Login</button>
      <button  id="register-btn">Register</button>
    </div>
  </nav>

</div>

</div>
</div>

  • Related