Search code examples
javascripthamburger-menu

How to make my burger menu dissapear when clicking on link


I created a burger menu which has the following JS:

const navSlide = () => {
  const burger = document.querySelector('.hamburger');
  const nav = document.querySelector('.nav-links');
  const navLinks = document.querySelectorAll('.nav-links li');

  burger.addEventListener('click', () => {
    // Open Menu
    burger.classList.toggle('no-shadow');
    nav.classList.toggle('nav-active');
    // Links fade efffect
    navLinks.forEach((link, index) => {
      if (link.style.animation) {
        link.style.animation = '';
      } else {
        link.style.animation = `navLinkFade .5s ease forwards ${index / 5 + .2}s`;
      }
      //ADDED
      link.addEventListener('click', () => {
        burger.classList.toggle('no-shadow');
        nav.classList.toggle('nav-active');
        burger.classList.toggle('toggle');
      });
      //ADDED
    });
    // Burger animation
    burger.classList.toggle('toggle');
  });
}
navSlide();
.nav-links {
    position: fixed;
    padding-top: 8rem;
    right: 0px;
    height: 70vh;
    top: 0;
    background-color: var(--branding);
    border-bottom-left-radius: 3rem;
    display: flex;
    flex-direction: column;
    text-align: left;
    padding: 3em;
    transform: translateX(100%);
    transition: transform .2s ease-in;
  }

  .nav-links li {
    opacity: 0;
  }

  .nav-links li a {
    font-size: 1rem ;
  }

.hamburger {
  margin: 1.5em;
  display: block;
  cursor: pointer;
  background-color: var(--branding);
  padding: 16px 12px;
  position: fixed;
  top: 0;
  right: 0;
  border-radius: 100%;
  box-shadow: 0 1.5rem 4rem rgba(0, 0, 0, .4);
}

.hamburger div {
  width: 25px;
  height: 2px;
  background-color: #d1d1d1;
  margin: 5px;
  transition: all .3s ease;
}

.nav-active {
  transform: translateX(0%);
}

.no-shadow {
  box-shadow: none;
}

@keyframes navLinkFade {
  from {
    opacity: 0;
    transform: translateX(50px);
  }
  to {
    opacity: 1;
    transform: translateX(0px);
  }
}

.toggle .line1 {
  transform: rotate(-405deg) translate(-5px, 5px);
}

.toggle .line2 {
  opacity: 0;
}

.toggle .line3 {
  transform: rotate(405deg) translate(-5px, -5px);
}
<ul class="nav-links">
  <li><a href="#abt">About</a></li>
  <li><a href="#srv">Services</a></li>
  <li><a href="#soc">Social</a></li>
  <li><a href="#inf">Contact</a></li>
</ul>

  

<div class="hamburger">
   <div class="line1"></div>
   <div class="line2"></div>
   <div class="line3"></div>
</div>

Here's what I found relevant to upload and related with my issue, it's almost working as i want it to but, as i said it won't show the links after the menu closes the first time. I added the burger styles as Mark requested.

Let me know if you need anything else.


Solution

  • I moved the click event listener of the links outside of the burger click event listener to avoid duplicate event bindings. I also changed the event listener of the links to programmatically trigger the hamburger click to hide it again.

    This way you don't have duplicated code. You want to avoid having to change code on 2 or more places when you change something.

    const navSlide = () => {
      const burger = document.querySelector('.hamburger');
      const nav = document.querySelector('.nav-links');
      const navLinks = document.querySelectorAll('.nav-links li');
    
      //Toggle burger
      burger.addEventListener('click', () => {
        burger.classList.toggle('no-shadow');
        nav.classList.toggle('nav-active');
        navLinks.forEach((link, index) => {
          if (link.style.animation) {
            link.style.animation = '';
          } else {
            link.style.animation = `navLinkFade .5s ease forwards ${index / 5 + .2}s`;
          }
        });
        burger.classList.toggle('toggle');
      });
      
      //Moved outside the burger event listner to avoid duplicate event bindings and let the event listener programmatically trigger the burger click to hide it again.
      navLinks.forEach((link, index) => {
        link.addEventListener('click', () => {
          burger.click();
        });
      });
    }
    navSlide();
    .nav-links {
      position: fixed;
      padding-top: 8rem;
      right: 0px;
      height: 70vh;
      top: 0;
      background-color: var(--branding);
      border-bottom-left-radius: 3rem;
      display: flex;
      flex-direction: column;
      text-align: left;
      padding: 3em;
      transform: translateX(100%);
      transition: transform .2s ease-in;
    }
    
    .nav-links li {
      opacity: 0;
    }
    
    .nav-links li a {
      font-size: 1rem;
    }
    
    .hamburger {
      margin: 1.5em;
      display: block;
      cursor: pointer;
      background-color: var(--branding);
      padding: 16px 12px;
      position: fixed;
      top: 0;
      right: 0;
      border-radius: 100%;
      box-shadow: 0 1.5rem 4rem rgba(0, 0, 0, .4);
    }
    
    .hamburger div {
      width: 25px;
      height: 2px;
      background-color: #d1d1d1;
      margin: 5px;
      transition: all .3s ease;
    }
    
    .nav-active {
      transform: translateX(0%);
    }
    
    .no-shadow {
      box-shadow: none;
    }
    
    @keyframes navLinkFade {
      from {
        opacity: 0;
        transform: translateX(50px);
      }
      to {
        opacity: 1;
        transform: translateX(0px);
      }
    }
    
    .toggle .line1 {
      transform: rotate(-405deg) translate(-5px, 5px);
    }
    
    .toggle .line2 {
      opacity: 0;
    }
    
    .toggle .line3 {
      transform: rotate(405deg) translate(-5px, -5px);
    }
    <ul class="nav-links">
      <li><a href="#abt">About</a></li>
      <li><a href="#srv">Services</a></li>
      <li><a href="#soc">Social</a></li>
      <li><a href="#inf">Contact</a></li>
    </ul>
    
    
    
    <div class="hamburger">
      <div class="line1"></div>
      <div class="line2"></div>
      <div class="line3"></div>
    </div>