How can I use click event properly in my custom navigation menu?

Viewed 125

I was trying to create an animated hamburger nav menu. The functionality is simple. It will be in a fixed position & incorporate in a circle. When I click that circle the background will overlap the entire screen & nav links will be visible. I have used pseudo-class to create functionality. it works well, but a little mistake appeared. When I clicked the nav links the background should scale to 0. But it is nowhere can be done using CSS. So I used JS click event for it. It worked for the first try after that the menu keep scaled to 0 unit. I need to fix it so that the js click event functionality reset itself on every try. The link is given below.

codepen here

Code-

const navElement = document.querySelector('.navigation__nav');
const navBackground = document.querySelector('.navigation__background');
const navgationList = document.querySelectorAll('.navigation__item');

navgationList.forEach(function(items) {
  let x = items;
  items.addEventListener('click', closeNav);

  function closeNav() {
    navElement.style.transform = 'scale(0)';
    navBackground.style.transform = 'scale(0)';
  }
});
body {
  background-color: cyan;
}

.navigation__checkbox {
  display: none;
}

.navigation__button {
  background-color: #fff;
  height: 7rem;
  width: 7rem;
  position: fixed;
  top: 6rem;
  right: 6rem;
  border-radius: 50%;
  z-index: 2000;
  box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.1);
  text-align: center;
  cursor: pointer;
}

@media only screen and (max-width: 56.25em) {
  .navigation__button {
    top: 4rem;
    right: 4rem;
  }
}

@media only screen and (max-width: 37.5em) {
  .navigation__button {
    top: 3rem;
    right: 3rem;
  }
}

.navigation__background {
  height: 6rem;
  width: 6rem;
  border-radius: 50%;
  position: fixed;
  top: 6.5rem;
  right: 6.5rem;
  background-image: radial-gradient(#4ea5f7, #0400ff);
  z-index: 1000;
  transition: transform 0.8s cubic-bezier(0.86, 0, 0.07, 1);
}

@media only screen and (max-width: 56.25em) {
  .navigation__background {
    top: 4.5rem;
    right: 4.5rem;
  }
}

@media only screen and (max-width: 37.5em) {
  .navigation__background {
    top: 3.5rem;
    right: 3.5rem;
  }
}

.navigation__nav {
  height: 100vh;
  position: fixed;
  top: 0;
  left: 0;
  z-index: 1500;
  opacity: 0;
  width: 0;
  transition: all 0.8s cubic-bezier(0.68, -0.55, 0.265, 1.55);
}

.navigation__list {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  list-style: none;
  text-align: center;
  width: 100%;
}

.navigation__item {
  margin: 1rem;
}

.navigation__link:link,
.navigation__link:visited {
  display: inline-block;
  font-size: 3rem;
  font-weight: 300;
  padding: 1rem 2rem;
  color: #fff;
  text-decoration: none;
  text-transform: uppercase;
  background-image: linear-gradient(120deg, transparent 0%, transparent 50%, #fff 50%);
  background-size: 220%;
  transition: all .4s;
}

.navigation__link:link span,
.navigation__link:visited span {
  margin-right: 1.5rem;
  display: inline-block;
}

.navigation__link:hover,
.navigation__link:active {
  background-position: 100%;
  color: #0400ff;
  transform: translateX(1rem);
}

.navigation__checkbox:checked~.navigation__background {
  transform: scale(80);
}

.navigation__checkbox:checked~.navigation__nav {
  opacity: 1;
  width: 100%;
}

.navigation__icon {
  position: relative;
  margin-top: 3.5rem;
}

.navigation__icon,
.navigation__icon::before,
.navigation__icon::after {
  width: 3rem;
  height: 2px;
  background-color: #333;
  display: inline-block;
}

.navigation__icon::before,
.navigation__icon::after {
  content: "";
  position: absolute;
  left: 0;
  transition: all .2s;
}

.navigation__icon::before {
  top: -.8rem;
}

.navigation__icon::after {
  top: .8rem;
}

.navigation__button:hover .navigation__icon::before {
  top: -1rem;
}

.navigation__button:hover .navigation__icon::after {
  top: 1rem;
}

.navigation__checkbox:checked+.navigation__button .navigation__icon {
  background-color: transparent;
}

.navigation__checkbox:checked+.navigation__button .navigation__icon::before {
  top: 0;
  transform: rotate(135deg);
}

.navigation__checkbox:checked+.navigation__button .navigation__icon::after {
  top: 0;
  transform: rotate(-135deg);
}
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Menu</title>
</head>

<body>

  <div class="navigation">
    <input type="checkbox" class="navigation__checkbox" id="navi-toggle">
    <label for="navi-toggle" class="navigation__button">
            <span class="navigation__icon">&nbsp;</span>
        </label>
    <div class="navigation__background">&nbsp;</div>
    <nav class="navigation__nav">
      <ul class="navigation__list">
        <li class="navigation__item"><a href="#our-works" class="navigation__link"><span>01</span> Our Works</a></li>
        <li class="navigation__item"><a href="#features-section" class="navigation__link"><span>02</span> Features</a></li>
        <li class="navigation__item"><a href="#our-services" class="navigation__link"><span>03</span> Our Services</a></li>
        <li class="navigation__item"><a href="#blog-section" class="navigation__link"><span>04</span> Blogs</a></li>
        <li class="navigation__item"><a href="#contact-us" class="navigation__link"><span>05</span> Contact Us</a></li>
        <li class="navigation__item"><a href="#" class="navigation__link"><span>06</span> Know About Author</a></li>
      </ul>
    </nav>
  </div>

</body>

</html>

[p.s.- comment out the js code first to see the working CSS.]

Although this is for practices hence any help will be a big help for me to understand js and dom.

2 Answers

I reworked a bit your closeNav function in order to get what you want working.

function closeNav(){
    navElement.style.transform = 'scale(0)';
    navBackground.style.transform = 'scale(0)';
    
    // setTimeout will be useful for resetting our elements once they 
    // reached scale(0)    
    setTimeout(() => {
      // You can check or uncheck a checkbox in javascript using .checked, 
      // here in order to set the styles back to normal.
      document.querySelector('.navigation__checkbox').checked = false;

      // Wait a bit more that the elements have been reset to remove the 
      // styles given in JS above.
      setTimeout(() => {
        navElement.style = '';
        navBackground.style = '';
      }, 500);
    }, 1000);
  }

You'll need to rework the timeouts so that they exactly meet your transition duration !

The CSS already handles what happens when the checkbox isn't checked. This works fine for me.

function closeNav(){
  document.querySelector('.navigation__checkbox').checked = false;     
}
Related