The Need for Multi-Level Dropdown Submenus
Dropdown menus are a staple of web design, allowing users to access a variety of options within a compact interface. However, in some cases, a single-level dropdown menu may not suffice. Imagine a scenario where you need to categorize menu items further into subcategories. This is where multi-level dropdown submenus come into play.
The Approach
To implement multi-level dropdown submenus in Bootstrap 5, we'll extend the default behavior of the Dropdown component using custom JavaScript. While Dropdown does not natively support multilevel submenus, we can leverage JavaScript and CSS to achieve this functionality.
Extending the Toggle Function
The heart of our solution lies in extending the behavior of the Dropdown component. By overriding the toggle
function of the Dropdown prototype, we can inject custom functionality.
We'll begin by overriding the toggle
function of the Dropdown component. This function is responsible for toggling the visibility of the dropdown menu. In our custom code, we will track parent .dropdown
elements and add a special class, .drd-submenu
, to indicate that a dropdown is part of a submenu.
(function ($bs) {
$bs.Dropdown.prototype.toggle = function (_orginal) {
return function () {
document.querySelectorAll('.drd-submenu').forEach(function (e) {
e.classList.remove('drd-submenu');
});
let drd = this._element.closest('.dropdown').parentNode.closest('.dropdown');
for (; drd && drd !== document; drd = drd.parentNode.closest('.dropdown')) {
drd.classList.add('drd-submenu');
}
return _orginal.call(this);
}
}($bs.Dropdown.prototype.toggle);
document.querySelectorAll('.dropdown').forEach(function (drd) {
drd.addEventListener('hide.bs.dropdown', function (e) {
if (this.classList.contains('drd-submenu')) {
this.classList.remove('drd-submenu');
e.preventDefault();
}
e.stopPropagation();
});
});
})(bootstrap);
We add an event listener to the hide.bs.dropdown
event to ensure proper behavior when closing the submenus. When the submenu is closed, this event listener removes the .drd-submenu
class from the parent .dropdown
element.
Dropdown Submenu Example
Here's an example of how you can create a multi-level dropdown submenu:
<div class="dropdown">
<a class="btn btn-secondary dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false"> Dropdown link </a>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#">Action</a></li>
<li><a class="dropdown-item" href="#">Another action</a></li>
<li><a class="dropdown-item" href="#">Something else here</a></li>
<li class="dropdown dropend">
<a class="dropdown-item dropdown-toggle" href="javascript:void(0);" data-bs-toggle="dropdown" aria-expanded="false">Submenu</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#">Submenu 1</a></li>
<li><a class="dropdown-item" href="#">Submenu 2</a></li>
<li><a class="dropdown-item" href="#">Submenu 3</a></li>
<li><a class="dropdown-item" href="#">Submenu 4</a></li>
<li class="dropdown dropend">
<a class="dropdown-item dropdown-toggle" href="javascript:void(0);" data-bs-toggle="dropdown" aria-expanded="false">Submenu 5</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#">Submenu 1</a></li>
<li><a class="dropdown-item" href="#">Submenu 2</a></li>
<li><a class="dropdown-item" href="#">Submenu 3</a></li>
<li><a class="dropdown-item" href="#">Submenu 4</a></li>
<li class="dropdown dropend">
<a class="dropdown-item dropdown-toggle" href="javascript:void(0);" data-bs-toggle="dropdown" aria-expanded="false">Submenu 5</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#">Submenu 1</a></li>
<li><a class="dropdown-item" href="#">Submenu 2</a></li>
<li><a class="dropdown-item" href="#">Submenu 3</a></li>
<li><a class="dropdown-item" href="#">Submenu 4</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
In this example, we're using the .dropend
class to make the dropdown submenu appear on the right side of the button. You can use these classes .dropstart
to open the left side and .dropup
to open the above.
Conclusion
While Bootstrap doesn't provide native support for multi-level dropdown submenus, this custom JavaScript solution allows developers to create this functionality by extending the behavior of the Dropdown component. By marking parent dropdowns and managing the .drd-submenu
class, we can achieve a multi-level dropdown submenu experience.