Search code examples
htmljquerycssdrop-down-menudropdown

How to create dropdown navigation using jQuery?


I tried creating a dropdown list that is visible when you hover over the link.

I want to create a navigation menu that drops links when hover over the link using jQuery.

I created a function such that when you hover over 'link 3' the dropdown will fall (using mouseenter and mouseleave). But when you move the mouse over the dropdown link it should remain the same but it is going up.

Also is it possible to force hover state on link 3 when you hover over the dropdown contents?

$(document).ready(function(){
 $("div#header ul li a#link-three").on('mouseenter', function(){
  $("div#header-dropdown-content").slideDown(500);
 });
 
 $("div#header ul li a#link-three").on('mouseleave', function(){
  $("div#header-dropdown-content").slideUp(500);
 });
 
 $("div#header-dropdown-content a").on('mouseenter', function(){
  $("div#header-dropdown-content").slideDown(500);
  $("a#link-three").trigger('hover');
 });
 
 $("div#header-dropdown-content a").on('mouseleave', function(){
  $("div#header-dropdown-content").slideUp(500);
 });
});
div#header {
 z-index: 1;
 position: sticky;
 top: 0;
}
div#header ul {
 list-style-type: none;
 user-select: none;
 font-size: 1.15em;
 margin: -8px;
 padding: 0;
 height: 43px;
 overflow: hidden;
 backdrop-filter: blur(3px);
 background: none;
 background-color: rgba(23 23 23 / 75%);
 box-shadow: 0 5px 10px 0 rgba(0 0 0 / 60%);
}
div#header ul li {
 float: left;
}
div#header ul li a {
 display: block;
 cursor: pointer;
 color: white;
 text-align: center;
 padding: 6px 16px;
 border: 4px solid transparent;
 text-decoration: none;
 transition: .5s border-bottom, .3s background;
}
div#header ul li a:hover {
 background: #222;
 border-bottom: 4px solid #f00;
}

div#header-dropdown-content {
 display: none;
 position: absolute;
 left: 114.5px;
 top: 43px;
 font-size: 17px;
 box-shadow: 0px 4px 9px #aaa;
 background: #f1f1f1;
 width: 157.5px;
}
div#header-dropdown-content a {
 color: black;
 text-decoration: none;
 display: flex;
 padding: 15px 10px;
}
div#header-dropdown-content a:hover {background: #ddd;}
<!DOCTYPE html>
<html><head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body>

<div id="header">
 <ul>
  <li><a href="javascript:void(0);" id="link-one">Link 1</a></li>
  <li><a href="javascript:void(0);" id="link-two">Link 2</a></li>
  <li><a href="javascript:void(0);" id="link-three">Link 3</a></li>
 </ul>
</div>

<div id="header-dropdown-content">
 <a href="javascript:void(0);">Dropdown 1</a>
 <a href="javascript:void(0);">Dropdown 2</a>
 <a href="javascript:void(0);">Dropdown 3</a>
 <a href="javascript:void(0);">Dropdown 4</a>
</div>

</body>


Solution

  • You could consider having some state variables that check whether the dropdown or the link is hovered. Show if either is true or hide if both are false.

    Since there is a slight gap between the hitbox of the link and the dropdown, have a delay before checking whether the dropdown should hide. This gives time for the user to move their mouse to the dropdown.

    $(document).ready(function(){
      let linkHovered = false;
      let dropdownHovered = false;
      let timeout;
      
      const check = () => {
        clearTimeout(timeout);
    
        if (linkHovered || dropdownHovered) {
          $("div#header-dropdown-content").slideDown(500);
        }
        else {
          timeout = setTimeout(() => {
            if (!linkHovered && !dropdownHovered) {
              $("div#header-dropdown-content").slideUp(500);
            }
          }, 200);
        }
      };
    
     $("div#header ul li a#link-three").on('mouseenter', function(){
       linkHovered = true;
       check();
     });
     
     $("div#header ul li a#link-three").on('mouseleave', function(event) {
       linkHovered = false;
       check();
     });
     
     $("div#header-dropdown-content a").on('mouseenter', function(){
       dropdownHovered = true;
       check();
     });
     
     $("div#header-dropdown-content a").on('mouseleave', function(){
       dropdownHovered = false;
       check();
     });
    });
    div#header {
     z-index: 1;
     position: sticky;
     top: 0;
    }
    div#header ul {
     list-style-type: none;
     user-select: none;
     font-size: 1.15em;
     margin: -8px;
     padding: 0;
     height: 43px;
     overflow: hidden;
     backdrop-filter: blur(3px);
     background: none;
     background-color: rgba(23 23 23 / 75%);
     box-shadow: 0 5px 10px 0 rgba(0 0 0 / 60%);
    }
    div#header ul li {
     float: left;
    }
    div#header ul li a {
     display: block;
     cursor: pointer;
     color: white;
     text-align: center;
     padding: 6px 16px;
     border: 4px solid transparent;
     text-decoration: none;
     transition: .5s border-bottom, .3s background;
    }
    div#header ul li a:hover {
     background: #222;
     border-bottom: 4px solid #f00;
    }
    
    div#header-dropdown-content {
     display: none;
     position: absolute;
     left: 114.5px;
     top: 43px;
     font-size: 17px;
     box-shadow: 0px 4px 9px #aaa;
     background: #f1f1f1;
     width: 157.5px;
    }
    div#header-dropdown-content a {
     color: black;
     text-decoration: none;
     display: flex;
     padding: 15px 10px;
    }
    div#header-dropdown-content a:hover {background: #ddd;}
    <!DOCTYPE html>
    <html><head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    </head>
    <body>
    
    <div id="header">
     <ul>
      <li><a href="javascript:void(0);" id="link-one">Link 1</a></li>
      <li><a href="javascript:void(0);" id="link-two">Link 2</a></li>
      <li><a href="javascript:void(0);" id="link-three">Link 3</a></li>
     </ul>
    </div>
    
    <div id="header-dropdown-content">
     <a href="javascript:void(0);">Dropdown 1</a>
     <a href="javascript:void(0);">Dropdown 2</a>
     <a href="javascript:void(0);">Dropdown 3</a>
     <a href="javascript:void(0);">Dropdown 4</a>
    </div>
    
    </body>