The solution can be found below
I have created a dropdown menu that currently shows the submenu on hover using the following CSS:
.main-menu ul li:hover > ul { display: block; }
However, my design requires the submenu to appear on click and stay visible until the user clicks elsewhere on the page (or on the close button in this case). From what I've gathered from similar questions like css hover to onclick conversation, it seems I need to utilize JavaScript's setAttribute
to add the class active
on click:
.main-menu ul li.active > ul { display: block; }
I've seen examples where people achieve this using the code snippet below which targets elements by their ID. However, since I cannot use the same ID for all my submenus, I'm looking for a more efficient way to target these elements without duplicating functions for each submenu. I've tried using classes and querySelectorAll()
to pinpoint the specific tags but seem to be missing something. Any guidance would be greatly appreciated.
window.onload = init;
function init()
{
document.getElementById('openSubmenu').onclick = openSubmenu;
document.getElementById('closeSubmenu').onclick = closeSubmenu;
}
function openSubmenu()
{
document.getElementById('openSubmenu').setAttribute('class','active');
}
function closeSubmenu()
{
document.getElementById('openSubmenu').removeAttribute('class','active');
}
HTML:
<div id="closeSubmenu">Close submenu</div>
<nav>
<div class="main-menu">
<ul>
<li><a href="#">Home</a></li>
<li id="openSubmenu"><a href="#">Dropdown 1</a>
<ul>
<li><a href="#">First tier</a></li>
<li><a href="#">First tier</a></li>
</ul>
</li>
<li><a href="#">Dropdown 2</a>
<ul>
<li><a href="#">First tier</a></li>
<li><a href="#">First tier</a></li>
<li><a href="#">First tier</a></li>
</ul>
</li>
<li><a href="#">Link</a></li>
<li><a href="#">Link</a></li>
</ul>
</div>
</nav>
CSS:
.main-menu {
width: 100%;
left: 0;
}
.main-menu ul {
position: relative;
text-align: center;
}
.main-menu ul li { display: inline-block; }
.main-menu li a {
line-height: 40px;
padding: 10px 20px;
text-transform: uppercase;
text-decoration: none;
color: #494949;
}
/* Hide dropdowns by default */
.main-menu ul ul {
width: 100%;
position: absolute;
display: none;
left: 0;
background-color: #c6c6c6;
}
/* Display Dropdowns on Hover */
.main-menu ul li:hover > ul { display: block; }
/* Display Dropdowns on Click */
.main-menu ul li.active > ul { display: block; }
SOLUTION
Below is the updated code where the relevant submenus now open on click, close when you click again on the submenu name, and also close when you click on a regular "non-submenu" element.
HTML
<nav> <ul> <li class="menuItem"><a href="#">Home</a></li> <li class="submenu"><a href="#">Dropdown 1</a> <ul> <li><a href="#">First tier</a></li> <li><a href="#">First tier</a></li> </ul> </li> <li class="submenu"><a href="#">Dropdown 2</a> <ul> <li><a href="#">First tier</a></li> <li><a href="#">First tier</a></li> <li><a href="#">First tier</a></li> </ul> </li> <li class="menuItem"><a href="#">Link</a></li> <li class="menuItem"><a href="#">Link</a></li> </ul> </nav>
CSS
nav { width: 100%; left: 0; } nav ul { position: relative; text-align: center; } nav ul li { display: inline-block; } nav li a { line-height: 40px; padding: 10px 20px; text-transform: uppercase; text-decoration: none; color: #494949; } /* Hide dropdowns by default */ nav ul ul { width: 100%; position: absolute; display: none; left: 0; background-color: #c6c6c6; } /* Display Dropdowns on Click */ nav ul li.active > ul { display: block; }
JS
window.onload = init; function init() { // set-up regular buttons var menuItemElements = document.getElementsByClassName('menuItem'); for (var i = 0; i < menuItemElements.length; i++) { menuItemElements[i].onclick = resetSubmenus; } // set-up buttons with submenu resetSubmenus(); } function openSubmenu() { resetSubmenus(); this.setAttribute('class','submenu active'); this.onclick = resetSubmenus; } function resetSubmenus() { var submenuElements = document.getElementsByClassName('submenu'); for (var i = 0; i < submenuElements.length; i++) { submenuElements[i].setAttribute('class','submenu'); submenuElements[i].onclick = openSubmenu; } }