skip to Main Content

I am creating a dropdown menu but there is a bug when using the vertical version for mobile phones and small devices.

THE PROBLEM:

When hovering, the first time hovering over one of the "main-categories" it will follow the css instructions and show you the correct black background color and white font color.

But then, if you hover on another of the "main-categories" the hover instruction for background black and font color white is not longer working.

Let me explain it better. The "main-categories" are:

news
politics
economy
health
education
culture

If you hover on politics, you will see the back background with white text on hover on politics. Now hover on Economy or education and you will see what I mean.

This only happens when hovering down, items under the first chosen category.

If you start the first hover on Education and then you go up hovering all other categories all the way up, it will work perfect but not when hovering down.

Here is the HTML

<nav class="menu">
  <main-categories><a href="#void">News</a>
    <sub-categories>
      <a href="#">Europe</a>
      <a href="#">Asia</a>
      <a href="#">Africa</a>
      <a href="#">Oceania</a>
      <a href="#">North America</a>
      <a href="#">South America</a>
    </sub-categories>
  </main-categories>

  <main-categories><a href="#void">Politics</a>
    <sub-categories>
      <a href="#">Europe</a>
      <a href="#">Asia</a>
      <a href="#">Africa</a>
      <a href="#">Oceania</a>
      <a href="#">North America</a>
      <a href="#">South America</a>
    </sub-categories>
  </main-categories>

  <main-categories><a href="#void">Economy</a>
    <sub-categories>
      <a href="#">Europe</a>
      <a href="#">Asia</a>
      <a href="#">Africa</a>
      <a href="#">Oceania</a>
      <a href="#">North America</a>
      <a href="#">South America</a>
    </sub-categories>
  </main-categories>

  <main-categories><a href="#void">Health</a>
    <sub-categories>
      <a href="#">Europe</a>
      <a href="#">Asia</a>
      <a href="#">Africa</a>
      <a href="#">Oceania</a>
      <a href="#">North America</a>
      <a href="#">South America</a>
    </sub-categories>
  </main-categories>

  <main-categories><a href="#void">Education</a>
    <sub-categories>
      <a href="#">Europe</a>
      <a href="#">Asia</a>
      <a href="#">Africa</a>
      <a href="#">Oceania</a>
      <a href="#">North America</a>
      <a href="#">South America</a>
    </sub-categories>
  </main-categories>

  <main-categories><a href="#void">Culture</a>
</main-categories>
</nav>

And here is the CSS

body,
html {
  margin: 0;
  padding: 0;
  border: 0;
  outline: 0;
  box-sizing: border-box;
  text-align: center;
  width: 100%;
  height: 100%;
}
body {
  background-color: #ffffff;
  font-family: "IBM Plex Serif", serif;
  font-size: 16px;
  font-weight: 400;
  color: #121212;
}
a {
  color: #121212;
  text-decoration: none;
}
a:hover {
  color: #e5633f;
}

nav {
  margin: 0 auto;
  width: 50%;

  display: block;
  text-align: center;
  border-bottom: 3px solid #121212;
}

main-categories {
  display: block;
  position: relative;
  width: 92%;
  margin: 0 auto;
  overflow: hidden;
  height: auto;
  text-align: left;
}
main-categories a {
  display: block;
  position: relative;
  width: 100%;
  height: 42px;
  line-height: 42px;
  font-size: 1em;
  text-transform: uppercase;
  text-align: left;
  border-bottom: 1px dotted #121212;
}
main-categories a:before {
  content: "▪ ";
}
main-categories a:last-child {
  border: 0;
}
main-categories a:hover {
  color: #ffffff;
  background-color: #121212;
  padding-left: 25px;
}
main-categories:last-child {
  border: 0;
}
main-categories a:hover:before {
  content: "▪ News ▪ ";
}
main-categories:first-child a:hover:before {
  content: "▪ My Site ▪ ";
}
sub-categories {
  display: none;
  position: relative;
  width: auto;
  height: auto;
  text-align: left;
  overflow: hidden;
  padding-left: 25px;
  padding-right: 25px;
  margin: 0 auto;
}
sub-categories a {
  display: block;
  font-size: 0.938em;
  color: #121212;
  text-transform: capitalize;
  text-align: left;
  height: 38px;
  line-height: 38px;
  border-bottom: 1px dotted #121212;
}
sub-categories a:hover {
  color: #e5633f;
  background-color: inherit;
  padding-left: 0px;
  text-transform: capitalize;
}
sub-categories a:last-child {
  border-bottom: 1px dotted #121212;
}
main-categories:hover sub-categories {
  display: block;
}
sub-categories a:before {
  content: "• ";
}
sub-categories a:hover:after {
  content: "";
}
main-categories:nth-of-type(1) sub-categories a:hover:before {
  content: "• My Site •  News • ";
}
main-categories:nth-of-type(2) sub-categories a:hover:before {
  content: "• News • Politics • ";
}
main-categories:nth-of-type(3) sub-categories a:hover:before {
  content: "• News • Economy • ";
}
main-categories:nth-of-type(4) sub-categories a:hover:before {
  content: "• News • Health • ";
}
main-categories:nth-of-type(5) sub-categories a:hover:before {
  content: "• News • Education • ";
}

I created a Codepen to see it working live and to test the bug.
https://codepen.io/familias/pen/XWygWzY

To test the bug:
on desktop just hover with your mouse all the way down and then all the way up, you will notice when you hover all the way down there is no black background with white text, but if you do it going up you will see it working fine.

On mobile devices touch all the way up and then down and you will see the same bug.

Now the big question: How to fix that?

2

Answers


  1. The issue is that the :hover: rule that does the white-on-black look only works when that <a> has the pseudo-class. What you want is for that <a> to be highlighted when anything in the main category is highlighted. Here’s how I would do that:

    body,
    html {
      margin: 0;
      padding: 0;
      border: 0;
      outline: 0;
      box-sizing: border-box;
      text-align: center;
      width: 100%;
      height: 100%;
    }
    body {
      background-color: #ffffff;
      font-family: "IBM Plex Serif", serif;
      font-size: 16px;
      font-weight: 400;
      color: #121212;
    }
    a {
      color: #121212;
      text-decoration: none;
    }
    a:hover {
      color: #e5633f;
    }
    
    nav {
      margin: 0 auto;
      width: 50%;
    
      display: block;
      text-align: center;
      border-bottom: 3px solid #121212;
    }
    
    main-categories {
      display: block;
      position: relative;
      width: 92%;
      margin: 0 auto;
      overflow: hidden;
      height: auto;
      text-align: left;
    }
    main-categories a, main-categories h4 {
      display: block;
      position: relative;
      width: 100%;
      height: 42px;
      line-height: 42px;
      font-size: 1em;
      text-transform: uppercase;
      text-align: left;
      border-bottom: 1px dotted #121212;
    }
    main-categories h4 {
      margin: 0;
    }
    main-categories a:before {
      content: "▪ ";
    }
    main-categories a:last-child {
      border: 0;
    }
    main-categories:hover h4 {
      color: #ffffff;
      background-color: #121212;
      padding-left: 25px;
    }
    main-categories:last-child {
      border: 0;
    }
    main-categories a:hover:before {
      content: "▪ News ▪ ";
    }
    main-categories:first-child:hover h4:before {
      content: "▪ Svea Times ▪ ";
    }
    sub-categories {
      display: none;
      position: relative;
      width: auto;
      height: auto;
      text-align: left;
      overflow: hidden;
      padding-left: 25px;
      padding-right: 25px;
      margin: 0 auto;
    }
    sub-categories a {
      display: block;
      font-size: 0.938em;
      color: #121212;
      text-transform: capitalize;
      text-align: left;
      height: 38px;
      line-height: 38px;
      border-bottom: 1px dotted #121212;
    }
    sub-categories a:hover {
      color: #e5633f;
      background-color: inherit;
      padding-left: 0px;
      text-transform: capitalize;
    }
    sub-categories a:last-child {
      border-bottom: 1px dotted #121212;
    }
    main-categories:hover sub-categories {
      display: block;
    }
    sub-categories a:before {
      content: "• ";
    }
    sub-categories a:hover:after {
      content: "";
    }
    main-categories:nth-of-type(1) sub-categories a:hover:before {
      content: "• Svea Times •  News • ";
    }
    main-categories:nth-of-type(2) sub-categories a:hover:before {
      content: "• News • Politics • ";
    }
    main-categories:nth-of-type(3) sub-categories a:hover:before {
      content: "• News • Economy • ";
    }
    main-categories:nth-of-type(4) sub-categories a:hover:before {
      content: "• News • Health • ";
    }
    main-categories:nth-of-type(5) sub-categories a:hover:before {
      content: "• News • Education • ";
    }
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Serif:wght@300;400;500&family=Playfair+Display:wght@400;700&display=swap" rel="stylesheet">
    
    <nav class="menu">
      <main-categories><h4>News</h4>
        <sub-categories>
          <a href="#">Europe</a>
          <a href="#">Asia</a>
          <a href="#">Africa</a>
          <a href="#">Oceania</a>
          <a href="#">North America</a>
          <a href="#">South America</a>
        </sub-categories>
      </main-categories>
    
      <main-categories><h4>Politics</h4>
        <sub-categories>
          <a href="#">Europe</a>
          <a href="#">Asia</a>
          <a href="#">Africa</a>
          <a href="#">Oceania</a>
          <a href="#">North America</a>
          <a href="#">South America</a>
        </sub-categories>
      </main-categories>
    
      <main-categories><h4>Economy</h4>
        <sub-categories>
          <a href="#">Europe</a>
          <a href="#">Asia</a>
          <a href="#">Africa</a>
          <a href="#">Oceania</a>
          <a href="#">North America</a>
          <a href="#">South America</a>
        </sub-categories>
      </main-categories>
    
      <main-categories><h4>Health</h4>
        <sub-categories>
          <a href="#">Europe</a>
          <a href="#">Asia</a>
          <a href="#">Africa</a>
          <a href="#">Oceania</a>
          <a href="#">North America</a>
          <a href="#">South America</a>
        </sub-categories>
      </main-categories>
    
      <main-categories><h4>Education</h4>
        <sub-categories>
          <a href="#">Europe</a>
          <a href="#">Asia</a>
          <a href="#">Africa</a>
          <a href="#">Oceania</a>
          <a href="#">North America</a>
          <a href="#">South America</a>
        </sub-categories>
      </main-categories>
    
      <main-categories><h4>Culture</h4></main-categories>
    
    </nav>

    (It’s hard to see that because of the small size of the snippet frame, but you can hit the "Full page" thing.)

    Substituting an <h4> for the header label is the main thing I did, with a couple other necessary tweaks. If you want to stick with an <a> there, you can give it a class (like "header") and then substitute a.header in the modified CSS and that should work also.

    Note that there’s still the issue that when you move down gradually and get to the next main section, it pops open but of course the mouse is now over something that’s not the first entry in the sublist. I don’t know any way to deal with that; I mean, the mouse is where it is.

    Also I haven’t tested it on a mobile device.

    Login or Signup to reply.
  2. You can not do it with :hover because the area your mouse hovers over is moved upward when the submenu opens.

    • Let the Web Component handle it, add an open state on <main-categories>.

    • A onmouseenter EventHandler will set/remove the open state:

    HTML:

      <main-categories open><a href="#void">News</a>
    

    CSS:

    main-categories[open] a {
      color: #ffffff;
      background-color: #121212;
      padding-left: 25px;
    }
    main-categories[open] sub-categories {
      display: block;
    }
    

    JavaScript:

    customElements.define("main-categories",class extends HTMLElement{
        connectedCallback(){
          this.onmouseenter = () => {
            this.parentNode
                .querySelectorAll("main-categories[open]")
                .forEach(cat => {
                                  cat.removeAttribute("open");
                                });
            this.setAttribute("open",true);
          }
      }
    })
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search