skip to Main Content

I have a component that when one of the 5 navigation items are hovered on, a mega menu appears (and remains visible until loses focus or closed).

Currently, whenever the close button is clicked, I add a class of display: none to the mega-menu to hide from view. However, this means that the mega-menu cannot be re-opened (when a user hovers again).

How can I toggle these classes so that the button actually closes the mega-menu but doesn’t impede future interactions?

const desktopMegaMenu = document.querySelector('.mega-menu');
const desktopCloseBtn = document.querySelector('.close-btn-desktop');

desktopCloseBtn.addEventListener('click', () => {
    desktopMegaMenu.classList.add('hide');
});
.container {
  max-height: 112px;
  
}

.nav-menu {
  min-height: 112px;
  padding-left: 5.6rem;
  padding-right: 5.6rem;
  background-color: green;
  display: flex;
  gap: 24px;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}

.nav-menu li {
  list-style: none;
  pointer-events: all;
}

.nav-menu li a {
  color: white;
  text-decoration: none;
  padding-top: 47px;
  padding-bottom: 47px;
}

.nav-menu li a:hover{
  text-decoration: underline;
}

.mega-menu {
  visibility: hidden;
  opacity: 0;
  position: absolute;
  background-color: lightblue;
  width: 100%;
  min-height: 250px;
  top: 128px;
  text-align: center;
}

.nav-menu:hover + .mega-menu {
  visibility: visible; 
  opacity: 1;
}

.mega-menu:hover {
  visibility: visible; 
  opacity: 1;
}

.hide {
  display: none;
}
<div class="container">
  <ul class="nav-menu">
    <li>
      <a href="#">Navigation item</a>
    </li>
    <li>
      <a href="#">Navigation item</a>
    </li>
    <li>
      <a href="#">Navigation item</a>
    </li>
    <li>
      <a href="#">Navigation item</a>
    </li>
    <li>
      <a href="#">Navigation item</a>
    </li>
  </ul>

  <div class="mega-menu">
This mega menu is visible when a nav item is hovered on, or the mega menu itself is being hovered on. 

The problem I am facing is that when the user closes to the mega menu (by adding display: none) - future interactions no longer display the mega menu.
    <button class="close-btn-desktop">Close mega menu</button>
  </div>
</div>

4

Answers


  1. After pressing the close button, the menu no longer appears, because the newly added class hide always exists, so the display is also none after re-hover.

    I added a piece of javascript for you to remove the hide class when hovering, as follows:

    const desktopMegaMenu = document.querySelector('.mega-menu');
    const desktopCloseBtn = document.querySelector('.close-btn-desktop');
    
    desktopCloseBtn.addEventListener('click', () => {
      desktopMegaMenu.classList.add('hide');
    });
    
    //New js
    //Use to remove the hide class when hover
    const navMenu = document.querySelector('.nav-menu');
    
    navMenu.addEventListener('mouseover', () => {
      desktopMegaMenu.classList.remove('hide');
    });
    .container {
      max-height: 112px;
    }
    
    .nav-menu {
      min-height: 112px;
      padding-left: 5.6rem;
      padding-right: 5.6rem;
      background-color: green;
      display: flex;
      gap: 24px;
      align-items: center;
      justify-content: center;
      pointer-events: none;
    }
    
    .nav-menu li {
      list-style: none;
      pointer-events: all;
    }
    
    .nav-menu li a {
      color: white;
      text-decoration: none;
      padding-top: 47px;
      padding-bottom: 47px;
    }
    
    .nav-menu li a:hover{
      text-decoration: underline;
    }
    
    .mega-menu {
      visibility: hidden;
      opacity: 0;
      position: absolute;
      background-color: lightblue;
      width: 100%;
      min-height: 250px;
      top: 128px;
      text-align: center;
    }
    
    .nav-menu:hover + .mega-menu {
      visibility: visible; 
      opacity: 1;
    }
    
    .mega-menu:hover {
      visibility: visible; 
      opacity: 1;
    }
    
    .hide {
      display:none;
    }
    <div class="container">
      <ul class="nav-menu">
        <li>
          <a href="#">Navigation item</a>
        </li>
        <li>
          <a href="#">Navigation item</a>
        </li>
        <li>
          <a href="#">Navigation item</a>
        </li>
        <li>
          <a href="#">Navigation item</a>
        </li>
        <li>
          <a href="#">Navigation item</a>
        </li>
      </ul>
    
      <div class="mega-menu">
    This mega menu is visible when a nav item is hovered on, or the mega menu itself is being hovered on. 
    
    The problem I am facing is that when the user closes to the mega menu (by adding display: none) - future interactions no longer display the mega menu.
        <button class="close-btn-desktop">Close mega menu</button>
      </div>
    </div>
    Login or Signup to reply.
  2. I suggest one solution :

    So I mostly use js function and removed your hover state in css, so there’s the same action in the same place.

    You can use a new function to add your visible class when hover a nav item, then remove it by clicking the close button :

    1: I added the "nav-link" class to your nav item ;

    2: I added one function "mouseover" on the nav item to make the big menu appear, by adding a class "is-visible" and remove it by clicking on the close button;

    3: I added the class "is-visible" in the css;

    const desktopMegaMenu = document.querySelector('.mega-menu');
    const desktopCloseBtn = document.querySelector('.close-btn-desktop');
    var links = document.querySelectorAll('.nav-link');
    
    links.forEach(link => {
      link.addEventListener('mouseover', function(){
        desktopMegaMenu.classList.add('is-visible');
      })
    });
    
    
    desktopCloseBtn.addEventListener('click', function(){
      desktopMegaMenu.classList.remove('is-visible')
    });
    .container {
      max-height: 112px;
      
    }
    
    .nav-menu {
      min-height: 112px;
      padding-left: 5.6rem;
      padding-right: 5.6rem;
      background-color: green;
      display: flex;
      gap: 24px;
      align-items: center;
      justify-content: center;
      pointer-events: none;
    }
    
    .nav-menu li {
      list-style: none;
      pointer-events: all;
    }
    
    .nav-menu li a {
      color: white;
      text-decoration: none;
      padding-top: 47px;
      padding-bottom: 47px;
    }
    
    .nav-menu li a:hover{
      text-decoration: underline;
    }
    
    .mega-menu {
      visibility: hidden;
      opacity: 0;
      position: absolute;
      background-color: lightblue;
      width: 100%;
      min-height: 250px;
      top: 128px;
      text-align: center;
    }
    
    /* .nav-menu:hover + .mega-menu {
      visibility: visible; 
      opacity: 1;
    } */
    
    .is-visible {
      visibility: visible; 
      opacity: 1;
    }
    
    .hide {
      display: none;
    }
    <div class="container">
      <ul class="nav-menu">
        <li class="nav-link">
          <a href="#">Navigation item</a>
        </li>
        <li class="nav-link">
          <a href="#">Navigation item</a>
        </li>
        <li class="nav-link">
          <a href="#">Navigation item</a>
        </li>
        <li class="nav-link">
          <a href="#">Navigation item</a>
        </li>
        <li class="nav-link">
          <a href="#">Navigation item</a>
        </li>
      </ul>
    
      <div class="mega-menu">
    This mega menu is visible when a nav item is hovered on, or the mega menu itself is being hovered on. 
    
    The problem I am facing is that when the user closes to the mega menu (by adding display: none) - future interactions no longer display the mega menu.
        <button class="close-btn-desktop">Close mega menu</button>
      </div>
    </div>

    I hope this will helps you 🙂

    Login or Signup to reply.
  3. The most obvious way, given your current approach, would be to remove the hide class from the element when the user moves the cursor back to the .nav-menu:

    const desktopMegaMenu = document.querySelector('.mega-menu');
    const desktopCloseBtn = document.querySelector('.close-btn-desktop');
    
    // new variable, caching the '.nav-menu' element:
    const navMenu = document.querySelector('.nav-menu');
    
    desktopCloseBtn.addEventListener('click', () => {
      desktopMegaMenu.classList.add('hide');
    });
    
    // using EventTarget.addEventListener() to bind the anonymous
    // Arrow function as the event-handler for the 'mouseenter'
    // event:
    navMenu.addEventListener('mouseenter', () => {
      // here use the Element.classList API to remove the
      // 'hide' class from the desktopMegaMenu element:
      desktopMegaMenu.classList.remove('hide')
    });
    .container {
      max-height: 112px;
    }
    
    .nav-menu {
      min-height: 112px;
      padding-left: 5.6rem;
      padding-right: 5.6rem;
      background-color: green;
      display: flex;
      gap: 24px;
      align-items: center;
      justify-content: center;
      pointer-events: none;
    }
    
    .nav-menu li {
      list-style: none;
      pointer-events: all;
    }
    
    .nav-menu li a {
      color: white;
      text-decoration: none;
      padding-top: 47px;
      padding-bottom: 47px;
    }
    
    .nav-menu li a:hover {
      text-decoration: underline;
    }
    
    .mega-menu {
      visibility: hidden;
      opacity: 0;
      position: absolute;
      background-color: lightblue;
      width: 100%;
      min-height: 250px;
      top: 128px;
      text-align: center;
    }
    
    .nav-menu:hover+.mega-menu {
      visibility: visible;
      opacity: 1;
    }
    
    .mega-menu:hover {
      visibility: visible;
      opacity: 1;
    }
    
    .hide {
      display: none;
    }
    <div class="container">
      <ul class="nav-menu">
        <li>
          <a href="#">Navigation item</a>
        </li>
        <li>
          <a href="#">Navigation item</a>
        </li>
        <li>
          <a href="#">Navigation item</a>
        </li>
        <li>
          <a href="#">Navigation item</a>
        </li>
        <li>
          <a href="#">Navigation item</a>
        </li>
      </ul>
    
      <div class="mega-menu">
        This mega menu is visible when a nav item is hovered on, or the mega menu itself is being hovered on. The problem I am facing is that when the user closes to the mega menu (by adding display: none) - future interactions no longer display the mega menu.
        <button class="close-btn-desktop">Close mega menu</button>
      </div>
    </div>
    Login or Signup to reply.
  4. You may use the following code:

    const desktopMegaMenu = document.querySelector('.mega-menu');
          const desktopCloseBtn = document.querySelector('.close-btn-desktop');
    const a = document.querySelectorAll("a");
          desktopCloseBtn.addEventListener('click', () => {
            desktopMegaMenu.style.visibility = "hidden";
          });
          
    a.forEach( element => {
          element.addEventListener('mouseover', () => {
            desktopMegaMenu.style.visibility = "visible";
          });
          });
    .container {
      max-height: 112px;
      
    }
    
    .nav-menu {
      min-height: 112px;
      padding-left: 5.6rem;
      padding-right: 5.6rem;
      background-color: green;
      display: flex;
      gap: 24px;
      align-items: center;
      justify-content: center;
      pointer-events: none;
    }
    
    .nav-menu li {
      list-style: none;
      pointer-events: all;
    }
    
    .nav-menu li a {
      color: white;
      text-decoration: none;
      padding-top: 47px;
      padding-bottom: 47px;
    }
    
    .nav-menu li a:hover{
      text-decoration: underline;
    }
    
    .mega-menu {
      visibility: hidden;
      opacity: 0;
      position: absolute;
      background-color: lightblue;
      width: 100%;
      min-height: 250px;
      top: 128px;
      text-align: center;
    }
    
    .nav-menu:hover + .mega-menu {
      visibility: visible; 
      opacity: 1;
    }
    
    .mega-menu:hover {
      visibility: visible; 
      opacity: 1;
    }
    <div class="container">
      <ul class="nav-menu">
        <li>
          <a href="#">Navigation item</a>
        </li>
        <li>
          <a href="#">Navigation item</a>
        </li>
        <li>
          <a href="#">Navigation item</a>
        </li>
        <li>
          <a href="#">Navigation item</a>
        </li>
        <li>
          <a href="#">Navigation item</a>
        </li>
      </ul>
    
      <div class="mega-menu">
    This mega menu is visible when a nav item is hovered on, or the mega menu itself is being hovered on. 
    
    The problem I am facing is that when the user closes to the mega menu (by adding display: none) - future interactions no longer display the mega menu.
        <button class="close-btn-desktop">Close mega menu</button>
      </div>
    </div>

    Hope you find this useful!

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