Accessible Multilevel Dropdown Menu with jQuery and CSS3
| File Size: | 3.43 KB |
|---|---|
| Views Total: | 7833 |
| Last Update: | |
| Publish Date: | |
| Official Website: | Go to website |
| License: | MIT |
A simple jQuery & CSS3 powered navigation script that helps you create a responsive, accessible, multi-level dropdown menu for your site navigation.
How to use it:
1. Create a multi-level dropdown navigation from nested html lists as displayed below.
<nav id="nav">
<ul>
<li> <a href="#">Top Level 1</a>
<ul>
<li><a href="#">Level 1-1</a></li>
<li><a href="#">Level 1-2</a></li>
<li><a href="#">Level 1-3</a>
<ul>
<li><a href="#">Level 3-1</a></li>
<li><a href="#">Level 3-2</a></li>
<li><a href="#">Level 3-3</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
2. The primary CSS styles for the navigation.
#nav, #nav ul, #nav li {
margin: 0;
padding: 0;
border: 0;
list-style: none;
box-sizing: border-box;
}
#nav {
position: relative;
min-height: 60px;
max-width: 100%;
background-color: #ffdb3a;
color: #000;
border: 1px solid #D9BA31;
}
#nav li { position: relative; }
#nav a {
text-decoration: none;
height: 100%;
display: block;
padding: 0 20px;
}
.plusMark {
margin-left: 10px;
font-size: 20px;
font-weight: 700;
}
#nav > ul, .fa {
height: 100%;
line-height: 60px;
}
#nav > ul > li {
position: relative;
text-align: center;
}
#nav > ul > li > a { background-color: #ffdb3a; }
#nav > ul > li > a:hover, #nav > ul > li > a:focus, #nav > ul > li > a.js-openSubMenu { background-color: #D9BA31; }
span#toggleMenu-text {
position: absolute;
opacity: 0;
}
3. The CSS styles for second and third level menus.
#nav > ul > li > ul { background-color: #D9BA31; }
#nav > ul > li > ul { background-color: #D9BA31; }
#nav > ul > li > ul > li > a { background-color: #D9BA31; }
#nav > ul > li > ul > li > a:hover, #nav > ul > li > ul > li > a:focus { background-color: #ffdb3a; }
#nav > ul > li > ul > li:not(:last-child) a { border-bottom: 1px solid #ffdb3a; }
#nav > ul > li > ul > li > ul > li > a { background-color: #ffdb3a; }
#nav > ul > li > ul > li > ul > li > a:hover, #nav > ul > li > ul > li > ul > li > a:focus { background-color: #D9BA31; }
#nav > ul > li > ul > li > ul > li:not(:last-child) > a { border-bottom: 1px solid #D9BA31; }
4. Javascript classes.
#nav .js-hideElement { display: none; }
#nav .js-showElement { display: block; }
5. Fallback for users without javascript.
html.no-js li:hover > a + ul, html.no-js li:focus > a + ul { display: block; }
6. Make the dropdown navigation responsive.
@media screen and (min-width: 650px) {
#nav { display: inline-block; }
}
@media screen and (max-width: 650px) {
#nav { display: block; }
}
@media screen and (min-width: 650px) {
#nav a:focus { outline: none; }
}
@media screen and (min-width: 650px) {
#nav li {
text-align: left;
width: 200px;
}
}
@media screen and (max-width: 650px) {
#nav li {
text-align: center;
width: 100%;
}
}
@media screen and (min-width: 650px) {
a + ul { position: absolute; }
a + ul:not(.js-showElement) { display: none; }
}
@media screen and (max-width: 650px) {
a + ul { position: relative; }
a + ul:not(.js-hideElement) { display: block; }
}
@media screen and (min-width: 650px) {
#nav > ul > li {
float: left;
width: auto;
}
}
@media screen and (max-width: 650px) {
#nav > ul > li {
float: none;
display: block;
width: 100%;
}
}
@media screen and (min-width: 650px) {
#nav > ul > li: not(: last-child) {
border-right: 1px solid #D9BA31;
border-bottom: none;
}
}
@media screen and (max-width: 650px) {
#nav > ul > li: not(: last-child) { border-right: none; }
#nav > ul > li:not(:last-child):not(:first-child) { border-bottom: 1px solid #D9BA31; }
}
#nav > ul > li:not(#toggleMenu):not(.js-showElement) { /* first level nav li except toggleMenu icon */ }
@media screen and (min-width: 650px) {
#nav > ul > li: not(#toggleMenu): not(.js-showElement) { display: inline-block; }
}
@media screen and (max-width: 650px) {
#nav > ul > li: not(#toggleMenu): not(.js-showElement) { display: none; }
}
@media screen and (min-width: 650px) {
#nav #toggleMenu { display: none; }
}
@media screen and (max-width: 650px) {
#nav #toggleMenu {
display: block;
width: 100%;
}
#nav #toggleMenu.js-open { border-bottom: 1px solid #D9BA31; }
#nav #toggleMenu.js-open .fa-times { display: block; }
#nav #toggleMenu.js-open .fa-bars { display: none; }
#nav #toggleMenu.js-open a { background-color: #D9BA31; }
#nav #toggleMenu:not(.js-open) .fa-times { display: none; }
#nav #toggleMenu:not(.js-open) .fa-bars { display: block; }
}
@media screen and (min-width: 650px) {
#nav > ul > li > ul {
top: 60px;
left: 0;
}
}
@media screen and (max-width: 650px) {
#nav > ul > li > ul {
width: 100%;
position: relative;
}
#nav > ul > li > ul:not(.js-showElement) { display: none; }
}
@media screen and (min-width: 650px) {
#nav > ul > li > ul > li > ul {
top: 0;
left: 200px;/* width of ul */
}
}
@media screen and (max-width: 650px) {
#nav > ul > li > ul > li > ul {
width: 100%;
position: relative;
}
#nav > ul > li > ul > li > ul:not(.js-showElement) { display: none; }
}
@media screen and (max-width: 650px) {
html.no-js #nav: hover > ul > li: not(#toggleMenu), html.no-js #nav: focus > ul > li: not(#toggleMenu) { display: block; }
html.no-js #nav:hover li:hover > a + ul, html.no-js #nav:hover li:focus > a + ul, html.no-js #nav:focus li:hover > a + ul, html.no-js #nav:focus li:focus > a + ul { display: block; }
}
7. Include the jQuery library at the bottom of your website.
<script src="//code.jquery.com/jquery-2.1.4.min.js"></script>
8. The core JavaScript to active the dropdown navigation.
$(document).ready(function() {
// Remove no-js class
$('html').removeClass('no-js');
$('#toggleMenu').on('click', function() {
if ($(this).hasClass('js-open')) {
$('#nav > ul > li:not(#toggleMenu)').removeClass('js-showElement');
$(this).removeClass('js-open');
} else {
$('#nav > ul > li:not(#toggleMenu)').addClass('js-showElement');
$(this).addClass('js-open');
}
return false;
})
// Add plus mark to li that have a sub menu
$('li:has("ul") > a').append('<span class="plusMark">+</span>');
// sub menu
// ------------------------
// When interacting with a li that has a sub menu
$('li:has("ul")').on('mouseover keyup click mouseleave', function(e) {
// If either -
// tabbing into the li that has a sub menu
// hovering over the li that has a sub menu
if (e.keyCode === 9 | e.type === 'mouseover') {
// Show sub menu
$(this).children('ul').removeClass('js-hideElement');
$(this).children('ul').addClass('js-showElement');
}
// If mouse leaves li that has sub menu
if (e.type === 'mouseleave') {
// hide sub menu
$(this).children('ul').removeClass('js-showElement');
$(this).children('ul').addClass('js-hideElement');
}
// If clicking on li that has a sub menu
if (e.type === 'click') {
// If sub menu is already open
if ($(this).children('a').hasClass('js-openSubMenu')) {
// remove Open class
$(this).children('a').removeClass('js-openSubMenu');
// Hide sub menu
$(this).children('ul').removeClass('js-showElement');
$(this).children('ul').addClass('js-hideElement');
// If sub menu is closed
} else {
// add Open class
$(this).children('a').addClass('js-openSubMenu');
// Show sub menu
$(this).children('ul').removeClass('js-hideElement');
$(this).children('ul').addClass('js-showElement');
}
return false;
} // end click event
});
// Tabbing through Levels of sub menu
// ------------------------
// If key is pressed while on the last link in a sub menu
$('li > ul > li:last-child > a').on('keydown', function(e) {
// If tabbing out of the last link in a sub menu AND not tabbing into another sub menu
if ((e.keyCode == 9) && $(this).parent('li').children('ul').length == 0) {
// Close this sub menu
$(this).parent('li').parent('ul').removeClass('js-showElement');
$(this).parent('li').parent('ul').addClass('js-hideElement');
// If tabbing out of a third level sub menu and there are no other links in the parent (level 2) sub menu
if ($(this).parent('li').parent('ul').parent('li').parent('ul').parent('li').children('ul').length > 0 && $(this).parent('li').parent('ul').parent('li').is(':last-child')) {
// Close the parent sub menu (level 2) as well
$(this).parent('li').parent('ul').parent('li').parent('ul').removeClass('js-showElement');
$(this).parent('li').parent('ul').parent('li').parent('ul').addClass('js-hideElement');
}
}
})
})
This awesome jQuery plugin is developed by anon. For more Advanced Usages, please check the demo page or visit the official website.











