ryrimsky
ryrimsky

Reputation: 25

Adding dropdown menu to navigation bar

Evening,

Learning on the job, currently doing a new website for my family business.

How can I make this drop down navigation menu work on desktop/mobile? I don’t want it too fancy, same design as the main navigation itself, I have fiddled around trying to make it work like the actual toggle so when users click ‘Services’ it would toggle down but it is not working as expected.

Ideally on hover it should display the drop down links for desktop, and mobile it should require a touch for it to display.

HTML

<div class="navigation-bar">
  <div class="navigation-item">
    <div class="logo">
      <a href="index.html">
        <img src="/assets/img/logo.jpg" alt="Company Logo">
      </a>
    </div>
    <ul class="navigation-bar-menu">
      <li class="active"><a href="index.html" class="active">Home</a></li>
      <li><a href="#">Services <i class="fa-thin fa-chevron-down"></i></a>

        <ul class="navigation-bar-dropdown">
          <li><a href="#">Managed Print Service</a></li>
          <li><a href="#">Document Management</a></li>
          <li><a href="#">Machine Finance Options</a></li>
          <li><a href="#">Machine Repair & Support</a></li>
        </ul>

      </li>
      <li><a href="#">Products <i class="fa-thin fa-chevron-down"></i></a>
        <ul class="navigation-bar-dropdown">
          <li><a href="#">Machines</a></li>
          <li><a href="#">Ricoh</a></li>
          <li><a href="#">Lexmark</a></li>
          <li><a href="#">Konica Minolta</a></li>
          <li><a href="#">Software</a></li>
          <li><a href="#">Kofax</a></li>
          <li><a href="#">Papercut</a></li>
          <li><a href="#">Filestar</a></li>
        </ul>
      </li>
      <li><a href="contact.html">Contact Us</a></li>
    </ul>
    <button class="navigation-bar-toggle">
      <i class="fa-light fa-bars"></i>
      Menu
    </button>
  </div>
</div>

CSS

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body {
  background-color: #242424;
  font-family: 'proxima-nova', sans-serif;
  font-weight: 100;
  font-style: normal;
  font-size: 16px;
  line-height: 1.5rem;
}

li {
  list-style-type: none;
}

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

.navigation-bar {
  background-color: #ffffff;
  padding: 2rem 1rem;
  position: relative;
  box-shadow: rgba(14, 30, 37, 0.12) 0px 2px 4px 0px, rgba(14, 30, 37, 0.32) 0px 2px 16px 0px;
}

.navigation-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.logo img {
  width: 10rem;
  display: block;
}

.navigation-bar-toggle {
  padding: 1rem;
  background-color: #ecf0f1;
  color: inherit;
  cursor: pointer;
  text-transform: uppercase;
  border: none;
  font: inherit;
  border-radius: 0.25rem;
}

.navigation-bar-dropdown {
  display: flex;
  flex-direction: column;
}

.navigation-bar-menu {
  flex-direction: column;
  right: 0;
  overflow: hidden;
  top: 100%;
  background: #ecf0f1;
  display: none;
  position: absolute;
  width: 100%;
}

.navigation-bar-menu .active {
  background-color: #242424;
  color: #ffffff;
  font-weight: 300;
}

.navigation-bar-menu li {
  display: flex;
  justify-content: center;
  padding: 1rem;
}

.navigation-bar-menu a {
  text-transform: uppercase;
}

.navigation-bar a:hover {
  opacity: 1 !important;
}

.navigation-bar-menu :not(.active):hover {
  background-color: #242424;
  color: #ffffff;
  opacity: 1;
  animation-name: fadeInOpacity;
  animation-iteration-count: 1;
  animation-timing-function: ease-in;
  animation-duration: 500ms;
}


.navigation-bar-menu.open {
  display: flex;
}

@media only screen and (min-width: 700px) {
 /* NAVIGATION BAR */
 .navigation-bar-toggle {
   display: none;
  }
  
  .navigation-bar-menu {
    display: flex;
    flex-direction: row;
    position: relative;
    background: none;
    justify-content: end;
    width: auto;
    gap: 1rem;
  }

  .navigation-bar-menu li {
    background-color: #ecf0f1;
    border-radius: 0.25rem;
    padding: 1rem;
  }
}

JS

  window.addEventListener('DOMContentLoaded', () => {
  const menuToggler = document.querySelector('.navigation-bar-toggle')
  const menu = document.querySelector('.navigation-bar-menu')

  menuToggler.addEventListener('click', () => {
    menu.classList.toggle('open')
  })
})

Any help would be greatly appreciated. https://jsfiddle.net/fc471p3e/4/

Upvotes: 2

Views: 108

Answers (1)

Dorji Tshering
Dorji Tshering

Reputation: 1021

Here, I did what I could to achieve what you wanted with minimal changes and added comments where necessary. Check it out once. Made changes in HTML markup, CSS and JS. Let me know in the comments if you want me to explain some changes or if there are things that needs some explanation. One thing, if you are adding a link that has dropdown, don't forget to add classnames as I did in your markup. I have also commented what classnames to add as well. You can go through it and feel free to leave a comment if something isn't clear.

window.addEventListener('DOMContentLoaded', () => {
  const menuToggler = document.querySelector('.navigation-bar-toggle');
  const menu = document.querySelector('.navigation-bar-menu');

  menuToggler.addEventListener('click', () => {
    menu.classList.toggle('open')
  })

  const linksWithChild = document.getElementsByClassName('dropdown-btn');

  for (let i = 0; i < linksWithChild.length; i++) {
    linksWithChild[i].addEventListener('click', function() {

      /* Upon clicking, check if any "dropdown-btn" other than the current one contains .active class. 
      If so remove .active class from the button and the dropdown will be hidden due to our style definition */
      for (let j = 0; j < linksWithChild.length; j++) {
        // 'this' refers to current dropdown-btn
        if (linksWithChild[j].classList.contains('active') && linksWithChild[j] !== this) {
          linksWithChild[j].classList.remove('active');
        }
      }
      this.classList.toggle('active');
    });
  }

})
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body {
  background-color: #242424;
  font-family: 'proxima-nova', sans-serif;
  font-weight: 100;
  font-style: normal;
  font-size: 16px;
  line-height: 1.5rem;
}

li {
  list-style-type: none;
}

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

.navigation-bar {
  background-color: #ffffff;
  padding: 2rem 1rem;
  position: relative;
  box-shadow: rgba(14, 30, 37, 0.12) 0px 2px 4px 0px, rgba(14, 30, 37, 0.32) 0px 2px 16px 0px;
}

.navigation-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.logo img {
  width: 10rem;
  display: block;
}

.navigation-bar-toggle {
  padding: 1rem;
  background-color: #ecf0f1;
  color: inherit;
  cursor: pointer;
  text-transform: uppercase;
  border: none;
  font: inherit;
  border-radius: 0.25rem;
}

.navigation-bar-menu {
  flex-direction: column;
  right: 0;
  top: 100%;
  background: #ecf0f1;
  display: none;
  position: absolute;
  width: 100%;
}

.navigation-bar-menu li.active a {
  background-color: #242424;
  color: #ffffff;
  font-weight: 300;
}

.navigation-bar-menu li {
  justify-content: center;
  position: relative;
}

.navigation-bar-menu a {
  text-transform: uppercase;
  padding: 1rem;
  background: #ecf0f1;
  display: inline-block;
  width: 100%;
}

.navigation-bar-dropdown {
  position: absolute;
  width: max-content;
  padding-top: 10px;
}

.has-child .navigation-bar-dropdown {
  display: none;
}

.navigation-bar-menu.open {
  display: flex;
}

@media only screen and (min-width: 700px) {
  /* navigation bar */
  .navigation-bar-toggle {
    display: none;
  }
  .has-child:hover .navigation-bar-dropdown {
    display: flex;
    flex-direction: column;
  }
  .navigation-bar-menu {
    display: flex;
    flex-direction: row;
    position: relative;
    background: none;
    justify-content: end;
    width: auto;
    gap: 1rem;
  }
  .navigation-bar-menu li a {
    border-radius: 0.25rem;
  }
}

@media screen and (max-width: 699px) {
  .has-child .navigation-bar-dropdown {
    position: relative;
    border-left: 2px solid #a5a7a8;
    margin-left: 30px;
  }
  /* show dropdown if the dropdown button has .active class */
  .has-child>a.active+.navigation-bar-dropdown {
    display: block;
  }
}


/* disable click evetns on devices that support hover */

@media screen and (hover: hover) and (pointer: fine) {
  .has-child>a {
    pointer-events: none;
  }
}
<div class="navigation-bar">
  <div class="navigation-item">
    <div class="logo">
      <a href="index.html">
        <img src="/assets/img/logo.jpg" alt="Company Logo">
      </a>
    </div>

    <!-- add .navlink class to every top level <li> tag -->
    <!-- add .has-child class to every .navlink <li> tag that has dropdown -->
    <!-- add .dropdown-btn class to direct <a> tag of .has-child <li> tag -->
    <ul class="navigation-bar-menu">
      <li class="navlink active"><a href="index.html" class="active">Home</a></li>
      <li class="navlink has-child">
        <a href="#" class="dropdown-btn">Services <i class="fa-thin fa-chevron-down"></i></a>
        <ul class="navigation-bar-dropdown">
          <li><a href="#">Managed Print Service</a></li>
          <li><a href="#">Document Management</a></li>
          <li><a href="#">Machine Finance Options</a></li>
          <li><a href="#">Machine Repair & Support</a></li>
        </ul>

      </li>
      <li class="navlink has-child">
        <a href="#" class="dropdown-btn">Products <i class="fa-thin fa-chevron-down"></i></a>
        <ul class="navigation-bar-dropdown">
          <li><a href="#">Machines</a></li>
          <li><a href="#">Ricoh</a></li>
          <li><a href="#">Lexmark</a></li>
          <li><a href="#">Konica Minolta</a></li>
          <li><a href="#">Software</a></li>
          <li><a href="#">Kofax</a></li>
          <li><a href="#">Papercut</a></li>
          <li><a href="#">Filestar</a></li>
        </ul>
      </li>
      <li class="navlink"><a href="contact.html">Contact Us</a></li>
    </ul>
    <button class="navigation-bar-toggle">
            <i class="fa-light fa-bars"></i>
            Menu
          </button>
  </div>
</div>

Upvotes: 1

Related Questions