5 Ways to Build a jQuery Dropdown Menu (With Copy-Paste Code)
This article shows five ways to build a dropdown menu with jQuery, each with copy-paste code.
The short answer: use slideUp/slideDown when you want motion, and addClass/removeClass when you want the look controlled from CSS. The HTML is identical in all five; only the way you toggle the submenu changes.
▼The five methods at a glance
| Method | Motion | Opens on |
|---|---|---|
slideUp/slideDown |
Slide | Hover |
addClass/removeClass |
Defined in CSS | Hover |
fadeIn/fadeOut |
Fade | Hover |
toggleClass |
Defined in CSS | Hover |
slideToggle |
Slide | Click |
Check which jQuery version you load. Versions before 3.5.0 carry two XSS vulnerabilities (CVE-2020-11022 and CVE-2020-11023) in htmlPrefilter, which affect DOM methods such as .html() and .append(). The snippets below now load 3.7.1. On a public site, load 3.5.1 or later.
- Using jQuery’s slideUp/slideDown
- Using jQuery’s
addClass/removeClass - Using jQuery’s addClass/removeClass
- jQueryの
fadeIn/fadeOutを使う - Using jQuery’s fadeIn/fadeOut
- Using jQuery’s
toggleClass - Using jQuery’s toggleClass
- Using jQuery’s slideToggle
- Using jQuery’s slideToggle (opens on click)
- Why hover-only menus break, and how to fix it
- Do you need jQuery for this at all?
- Summary
Using jQuery’s slideUp/slideDown
Here’s an implementation of a dropdown menu using jQuery’s slideUp and slideDown methods.
HTML
The .menuSub class contains the content that is displayed when the mouse hovers over it.
<div>
<ul class="menu">
<li>menu1</li>
<li>
menu2
<ul class="menuSub">
<li><a href="#">menu2-1</a></li>
<li><a href="#">menu2-2</a></li>
</ul>
</li>
<li>
menu3
<ul class="menuSub">
<li><a href="#">menu3-1</a></li>
<li><a href="#">menu3-2</a></li>
<li><a href="#">menu3-3</a></li>
</ul>
</li>
</ul>
</div>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
CSS
The .menuSub class is initially set to display: none; to hide it. The display toggle is managed by jQuery functions.
Other CSS rules are for styling the appearance.
.menu {
display: flex;
justify-content: flex-start;
list-style-type: none;
color: #fff;
padding: 0;
}
.menu li {
position: relative;
width: 100px;
margin-left: 1px;
padding: 5px;
background: #444444;
}
.menuSub {
position: absolute;
margin-left: -6px;
padding: 0;
display: none;
}
.menuSub li a {
padding: 5px;
margin-left: -5px;
margin-right: -5px;
margin-bottom: -5px;
display: block;
color: #fff;
text-decoration: none;
}
.menuSub li a:hover {
background: #FFCA7B;
}
jQuery/JS
When hovering over .menu li, the .menuSub is displayed using slideDown(). When the hover is removed, .menuSub is hidden using slideUp().
The :not(:animated) selector is essential. By using this, it prevents additional actions from being added while an animation is already running.
$(function() {
$("ul.menu li").hover(
function() {
$(".menuSub:not(:animated)", this).slideDown();
},
function() {
$(".menuSub", this).slideUp();
}
);
});
Using jQuery’s addClass/removeClass
Here is the implementation of a dropdown menu using jQuery’s addClass/removeClass.
Using jQuery’s addClass/removeClass
This approach toggles a class instead of animating directly. The look is defined entirely in CSS, so designers can change it without touching the JavaScript.
HTML
The part with the class .menuSub is the content that will be displayed when hovered over with the mouse.
<div>
<ul class="menu">
<li>menu1</li>
<li>
menu2
<ul class="menuSub">
<li><a href="#">menu2-1</a></li>
<li><a href="#">menu2-2</a></li>
</ul>
</li>
<li>
menu3
<ul class="menuSub">
<li><a href="#">menu3-1</a></li>
<li><a href="#">menu3-2</a></li>
<li><a href="#">menu3-3</a></li>
</ul>
</li>
</ul>
</div>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
CSS
There are two main points:
- Set
display: none;for the.menuSubclass to keep it hidden. - Set
display: block;for the.menuSub.openclass so that it becomes visible when hovered.
For the second point, when the mouse hovers, the jQuery implementation adds the .open class to the .menuSub element to display it.
Other CSS settings are for styling purposes.
.menu {
display: flex;
justify-content: flex-start;
list-style-type: none;
color: #fff;
padding: 0;
}
.menu li {
position: relative;
width: 100px;
margin-left: 1px;
padding: 5px;
background: #444444;
}
.menuSub {
position: absolute;
margin-left: -6px;
padding: 0;
display: none;
}
/*.openが付与された時、表示の設定*/
.menuSub.open {
display: block;
}
.menuSub li a {
padding: 5px;
margin-left: -5px;
margin-right: -5px;
margin-bottom: -5px;
display: block;
color: #fff;
text-decoration: none;
}
.menuSub li a:hover {
background: #FFCA7B;
}
jQuery/JS
When the mouse hovers, the addClass() method adds the .open class to the .menuSub element. Since the CSS settings display .menuSub.open, the menu will be shown.
When the mouse hover is removed, the removeClass() method removes the .open class. As per the CSS settings, .menuSub is set to be hidden, so the menu will be hidden.
$(function() {
$(".menu li").hover(
function() {
//クラス名「open」を付与する
$(this).children(".menuSub").addClass("open");
//hoverが外れた場合
}, function() {
//クラス名「open」を取り除く
$(this).children(".menuSub").removeClass("open");
}
);
});
jQueryのfadeIn/fadeOutを使う
In this method, fadeIn and fadeOut are used to control the menu’s visibility with a smooth fade animation. This makes the dropdown menu’s display more visually pleasant. The fade effect is applied through the hover event, so when the user hovers over the menu, the sub-menu gradually appears, and when the mouse is moved away, it gradually disappears.
Using jQuery’s fadeIn/fadeOut
This version fades the submenu in and out instead of sliding it. Only the opacity changes, so the layout never shifts.
HTML
<div>
<ul class="menu">
<li>menu1</li>
<li>
menu2
<ul class="menuSub">
<li><a href="#">menu2-1</a></li>
<li><a href="#">menu2-2</a></li>
</ul>
</li>
<li>
menu3
<ul class="menuSub">
<li><a href="#">menu3-1</a></li>
<li><a href="#">menu3-2</a></li>
<li><a href="#">menu3-3</a></li>
</ul>
</li>
</ul>
</div>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
CSS
.menu {
display: flex;
justify-content: flex-start;
list-style-type: none;
color: #fff;
padding: 0;
}
.menu li {
position: relative;
width: 100px;
margin-left: 1px;
padding: 5px;
background: #444444;
}
.menuSub {
position: absolute;
margin-left: -6px;
padding: 0;
display: none;
}
.menuSub li a {
padding: 5px;
margin-left: -5px;
margin-right: -5px;
margin-bottom: -5px;
display: block;
color: #fff;
text-decoration: none;
}
.menuSub li a:hover {
background: #FFCA7B;
}
jQuery/JS
$(function() {
$(".menu li").hover(
function() {
$(this).children(".menuSub").fadeIn();
},
function() {
$(this).children(".menuSub").fadeOut();
}
);
});
Using jQuery’s toggleClass
In this method, toggleClass is used to control the display and hiding of the submenu. By adding or removing the open class in response to the hover event, the styles defined in CSS are applied or removed accordingly. This makes toggling the state very simple, improving the readability and maintainability of the code.
Using jQuery’s toggleClass
This combines addClass and removeClass into a single method. You write the class name once instead of twice.
HTML
<div>
<ul class="menu">
<li>menu1</li>
<li>
menu2
<ul class="menuSub">
<li><a href="#">menu2-1</a></li>
<li><a href="#">menu2-2</a></li>
</ul>
</li>
<li>
menu3
<ul class="menuSub">
<li><a href="#">menu3-1</a></li>
<li><a href="#">menu3-2</a></li>
<li><a href="#">menu3-3</a></li>
</ul>
</li>
</ul>
</div>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
CSS
.menu {
display: flex;
justify-content: flex-start;
list-style-type: none;
color: #fff;
padding: 0;
}
.menu li {
position: relative;
width: 100px;
margin-left: 1px;
padding: 5px;
background: #444444;
}
.menuSub {
position: absolute;
margin-left: -6px;
padding: 0;
display: none;
}
.menuSub.open {
display: block;
}
.menuSub li a {
padding: 5px;
margin-left: -5px;
margin-right: -5px;
margin-bottom: -5px;
display: block;
color: #fff;
text-decoration: none;
}
.menuSub li a:hover {
background: #FFCA7B;
}
jQuery/JS
$(function() {
$(".menu li").hover(
function() {
$(this).children(".menuSub").toggleClass("open");
},
function() {
$(this).children(".menuSub").toggleClass("open");
}
);
});
Using jQuery’s slideToggle
slideToggle is a method that toggles the visibility of an element with a sliding animation. In this method, the sub-menu is either slid open or closed in response to a click event. By using the sliding effect, it provides users with a visual cue, making the opening and closing of the menu feel more intuitive.
Using jQuery’s slideToggle (opens on click)
The first four methods open on hover. This one opens on click, which is the only version of the five that works on touch devices.
HTML
<div>
<ul class="menu">
<li>menu1</li>
<li>
menu2
<ul class="menuSub">
<li><a href="#">menu2-1</a></li>
<li><a href="#">menu2-2</a></li>
</ul>
</li>
<li>
menu3
<ul class="menuSub">
<li><a href="#">menu3-1</a></li>
<li><a href="#">menu3-2</a></li>
<li><a href="#">menu3-3</a></li>
</ul>
</li>
</ul>
</div>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
CSS
.menu {
display: flex;
justify-content: flex-start;
list-style-type: none;
color: #fff;
padding: 0;
}
.menu li {
position: relative;
width: 100px;
margin-left: 1px;
padding: 5px;
background: #444444;
}
.menuSub {
position: absolute;
margin-left: -6px;
padding: 0;
display: none;
}
.menuSub li a {
padding: 5px;
margin-left: -5px;
margin-right: -5px;
margin-bottom: -5px;
display: block;
color: #fff;
text-decoration: none;
}
.menuSub li a:hover {
background: #FFCA7B;
}
jQuery/JS
$(function() {
$(".menu li").click(function() {
$(this).children(".menuSub").slideToggle();
});
});
Why hover-only menus break, and how to fix it
A dropdown that only opens on hover cannot be opened on a touch screen or with a keyboard. If the menu ships on a public site, add click support or keyboard support before you launch.
Phones and tablets have no hover state. Some browsers fire a synthetic hover on the first tap, but the behaviour differs between browsers and is not something to rely on. The slideToggle version above opens on click, which is the reliable choice for touch.
Keyboard users cannot hover either. Adding focus events lets people reach the menu with the Tab key.
$(function () {
$(".menu li").on("mouseenter focusin", function () {
$(this).children(".menuSub").slideDown();
});
$(".menu li").on("mouseleave focusout", function () {
$(this).children(".menuSub").slideUp();
});
});
Use focusin and focusout rather than focus and blur. The first pair bubbles, so the menu stays open when focus moves to a link inside it. The second pair does not, so the menu would close the moment the user tabs into it.
To tell screen readers whether the menu is open, add aria-expanded and point it at the submenu.
<button aria-expanded="false" aria-controls="submenu2">menu2</button>
<ul class="menuSub" id="submenu2">
<li><a href="#">menu2-1</a></li>
</ul>
Do you need jQuery for this at all?
No. A dropdown alone is not a reason to load jQuery. CSS can do it, and so can a built-in HTML element.
For a CSS-only version, show the submenu on hover and on focus within the parent. No JavaScript is loaded at all.
.menu li .menuSub {
display: none;
}
.menu li:hover .menuSub,
.menu li:focus-within .menuSub {
display: block;
}
Adding :focus-within makes the same menu work with a keyboard. Every major browser supports it.
If the menu should open on click, <details> and <summary> handle it natively. They open and close with no CSS and no JavaScript, and they are keyboard accessible out of the box.
<details>
<summary>menu2</summary>
<ul>
<li><a href="#">menu2-1</a></li>
<li><a href="#">menu2-2</a></li>
</ul>
</details>
▼Which one to pick
| Situation | Use |
|---|---|
| jQuery is already on the page | Any of the five methods above |
| No animation needed | CSS only (:hover + :focus-within) |
| Should open on click | <details> / <summary> |
| Needs fine-grained control | Plain JavaScript |
Every method here hides the submenu with display: none. That choice matters more than it looks: the difference between display, visibility and opacity when hiding elements decides whether the hidden links stay reachable by keyboard and screen readers.
While you are working on the menu markup, making the whole li clickable instead of just the text is worth applying to the submenu items. It removes the narrow hit area that makes small dropdown links frustrating to click.
Summary
In this article, we introduced various ways to implement a dropdown menu using jQuery.
- Using
slideUp/slideDownandaddClass/removeClass: Controls the opening and closing of the menu with animation effects. - Using
toggleClass: Adds and removes classes simply to toggle the menu’s visibility instantly. - Using
slideToggle: Provides a concise implementation of the slide animation to toggle the menu’s state with a click event. - Using
fadeIn/fadeOut: Smoothly controls the visibility of the menu with a fade effect.
Each method can be chosen based on the desired menu behavior and user experience. Whether you want to emphasize animation effects or simply toggle the menu state depends on the specific use case, so feel free to customize and choose the appropriate method. Try implementing the one that best suits your project.