Eric Nguyen
Eric Nguyen

Reputation: 1046

Hovering Issue With Nav Menu

My mega menu nav has a hovering issue. It activates when hovering over invisible child list items (mousing over from bottom to top, you'll notice the issue on this codepen).

This is the block of CSS that's triggering the hover:

.nav:hover > li > .subnav-block {
  opacity: 1;
  visibility: visible;
  overflow: visible;
}

I'm thinking a JavaScript solution would help out but trying to find CSS fix for this first.

Upvotes: 0

Views: 71

Answers (2)

Alain Cruz
Alain Cruz

Reputation: 5097

Your sub-navigation menu is taking up space, even though it is not visible. That is why you can see it whenever you are hovering above it. Adding height:0 to your .subnav-block and then setting it back to auto when hovering, should do the trick. Your css should look something like the one below.

.subnav-block {
  position: static;
  display: block;
  width: 100% !important;
  top: 54px;
  left: 0;
  height: 0;
  overflow: hidden;
  background: gray;
  -webkit-transition: all 0.3s ease 0.15s;
  -moz-transition: all 0.3s ease 0.15s;
  -o-transition: all 0.3s ease 0.15s;
  -ms-transition: all 0.3s ease 0.15s;
  transition: all 0.3s ease 0.15s;
}

.nav:hover > li > .subnav-block {
  height: auto;
  visibility: visible;
  overflow: visible;
}

UPDATE

If you want to add paddings to your sub-navigation menu, setting the height to 0 won't suffice, and you would need to change both the height and the padding when hovering. There is another way, which Hadi77 mentioned, which is setting the default display to none and then change it to block. Just like the example below.

.subnav-block {
  position: static;
  width: 100% !important;
  top: 54px;
  left: 0;
  display: none;
  background: gray;
  -webkit-transition: all 0.3s ease 0.15s;
  -moz-transition: all 0.3s ease 0.15s;
  -o-transition: all 0.3s ease 0.15s;
  -ms-transition: all 0.3s ease 0.15s;
  transition: all 0.3s ease 0.15s;
}

.nav:hover > li > .subnav-block {
  display: block;
}

UPDATE 2

Since display won't let us use transitions, the other workaround would be using a bit of JS. Since it is not much code, it is solid way to achieve this. We would need to remove the CSS hover in this.

JS

const nav = document.querySelectorAll('.nav > li');

nav.forEach(elem => {

  elem.addEventListener('mouseenter', () => {
    const subnav = document.querySelectorAll('.subnav-block');
    subnav.forEach(sub => {
      sub.classList.add('display-block');
      setTimeout( () => { 
        sub.style.opacity = 1;
        sub.style.height = 'auto';
      }, 100);
    });
  });

  elem.addEventListener('mouseleave', () => {
    const subnav = document.querySelectorAll('.subnav-block');
    subnav.forEach(sub => {
      sub.classList.remove('display-block');
      sub.style.opacity = 0;
    });
  });

});

CSS

.subnav-block {
  position: static;
  width: 100% !important;
  top: 54px;
  left: 0;
  display: none;
  opacity: 0;
  height: 0;
  background: gray;
  -webkit-transition: all 0.3s ease 0.15s;
  -moz-transition: all 0.3s ease 0.15s;
  -o-transition: all 0.3s ease 0.15s;
  -ms-transition: all 0.3s ease 0.15s;
  transition: all 0.3s ease 0.15s;
}

.display-block {
  display: block;
}

Upvotes: 2

Hadi77
Hadi77

Reputation: 137

Setting visibility to hidden, is somewhat like making it transparent: The element takes space as it should (display is set to block).

Using display property is what you want. Set it to none when you want the element to be "not displayed" and set it to block to "display it".


Also if you don't want all menus to drop-down together, move the :hover pseudo-selector in .nav:hover > li > .subnav-block to li, so it would become .nav > li:hover > .subnav-block.

Upvotes: 1

Related Questions