-
-
Save jmccall75/2718f3aef6500c756f6a405aa37ad911 to your computer and use it in GitHub Desktop.
Accessible WordPress Navigation Menu
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* An accessible menu for WordPress | |
*/ | |
(function($) { | |
var menuContainer = $('.menu-container'); | |
var menuToggle = menuContainer.find( '.menu-button' ); | |
var siteHeaderMenu = menuContainer.find( '#site-header-menu' ); | |
var siteNavigation = menuContainer.find( '#site-navigation' ); | |
// Toggles the menu button. | |
(function() { | |
if (!menuToggle.length) { | |
return; | |
} | |
// Add aria-expanded attribute to the menu. | |
menuToggle.add(siteNavigation).attr('aria-expanded', 'false'); | |
// Toggle the menu button. | |
menuToggle.on('click', function() { | |
// Add toggled-on class. | |
$(this).add(siteHeaderMenu).toggleClass('toggled-on'); | |
// Add aria-expanded attribute value to the menu. | |
$(this).add( siteNavigation ) | |
.attr('aria-expanded', $( this ) | |
.add( siteNavigation ).attr( 'aria-expanded' ) === 'false' ? 'true' : 'false' ); | |
} ); | |
} )(); | |
// Add the dropdown toggle button to menu items that have children menu items. | |
$('.menu-item-has-children > a').not(this).each(function(){ | |
// Get link text to prepend to screen reader text. | |
var linkText = $(this).text(); | |
// Define screen reader text. | |
var screenReaderText = {"expand":": submenu","collapse":": submenu"}; | |
// Set submenu button with screen reader text | |
var dropdownToggle = $('<button />', {'class': 'dropdown-toggle','aria-expanded': false}) | |
.append($('<span />', {'class': 'screen-readers',text: linkText+screenReaderText.expand})); | |
// Add submenu button after link | |
$(this).after(dropdownToggle); | |
}); | |
// Adds aria attribute to the site menu. | |
siteHeaderMenu.find( '.menu-item-has-children' ).attr( 'aria-haspopup', 'true' ); | |
// Toggles the submenu when dropdown toggle button is clicked. | |
siteHeaderMenu.find( '.dropdown-toggle' ).click( function(e) { | |
// close open submenus and reset attributes. | |
$('.dropdown-toggle').not(this).each(function(){ | |
$(this).removeClass( 'toggled-on' ); | |
$(this).nextAll( '.sub-menu' ).removeClass( 'toggled-on' ); | |
$(this).attr( 'aria-expanded', $(this).hasClass( 'toggled-on' ) === 'false' ? 'true' : 'false' ); | |
}); | |
// open current submenu and set attributes. | |
e.preventDefault(); | |
$(this).toggleClass( 'toggled-on' ); | |
$(this).nextAll( '.sub-menu' ).toggleClass( 'toggled-on' ); | |
$(this).attr( 'aria-expanded', $(this).attr( 'aria-expanded' ) === 'false' | |
? 'true' : 'false' ); | |
}); | |
// Adds a class to sub-menus for styling. | |
$('.sub-menu .menu-item-has-children').parent('.sub-menu').addClass('has-sub-menu'); | |
// Keyboard navigation. | |
$('.menu-item a, button.dropdown-toggle').on('keydown', function(e) { | |
if ([37,38,39,40,27].indexOf(e.keyCode) == -1) { | |
return; | |
} | |
switch(e.keyCode) { | |
case 27: // escape key | |
$(this).parents('ul').first().prev('.dropdown-toggle.toggled-on').focus(); | |
$(this).parents('ul').first().prev('.dropdown-toggle.toggled-on').click(); | |
break; | |
case 37: // left key | |
e.preventDefault(); | |
e.stopPropagation(); | |
if ($(this).hasClass('dropdown-toggle')){ | |
$(this).prev('a').focus(); | |
} | |
else { | |
if ($(this).parent().prev().children('button.dropdown-toggle').length) { | |
$(this).parent().prev().children('button.dropdown-toggle').focus(); | |
} | |
else { | |
$(this).parent().prev().children('a').focus(); | |
} | |
} | |
if ($(this).is('ul ul ul.sub-menu.toggled-on li:first-child a')) { | |
$(this).parents('ul.sub-menu.toggled-on li').children('button.dropdown-toggle').focus(); | |
} | |
break; | |
case 39: // right key | |
e.preventDefault(); | |
e.stopPropagation(); | |
if($(this).next('button.dropdown-toggle').length) { | |
$(this).next('button.dropdown-toggle').focus(); | |
} | |
else { | |
$(this).parent().next().children('a').focus(); | |
} | |
if ($(this).is('ul.sub-menu .dropdown-toggle.toggled-on')){ | |
$(this).parent().find('ul.sub-menu li:first-child a').focus(); | |
} | |
break; | |
case 40: // down key | |
e.preventDefault(); | |
e.stopPropagation(); | |
if($(this).next().length){ | |
$(this).next().find('li:first-child a').first().focus(); | |
} else { | |
$(this).parent().next().children('a').focus(); | |
} | |
if (($(this).is('ul.sub-menu a')) && ($(this).next('button.dropdown-toggle').length)) { | |
$(this).parent().next().children('a').focus(); | |
} | |
if (($(this).is('ul.sub-menu .dropdown-toggle')) && ($(this).parent().next().children('.dropdown-toggle').length)) { | |
$(this).parent().next().children('.dropdown-toggle').focus(); | |
} | |
break; | |
case 38: // up key | |
e.preventDefault(); | |
e.stopPropagation(); | |
if($(this).parent().prev().length){ | |
$(this).parent().prev().children('a').focus(); | |
} else { | |
$(this).parents('ul').first().prev('.dropdown-toggle.toggled-on').focus(); | |
} | |
if (($(this).is('ul.sub-menu .dropdown-toggle')) && ($(this).parent().prev().children('.dropdown-toggle').length)) { | |
$(this).parent().prev().children('.dropdown-toggle').focus(); | |
} | |
break; | |
} | |
}); | |
})(jQuery); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.menu-container:after { | |
display: table; | |
clear: both; | |
content: ""; | |
} | |
.site-header-menu { | |
display: none; | |
font-size: 1rem; | |
clear: both; | |
} | |
.main-navigation ul { | |
margin: 0; | |
padding: 0; | |
list-style: none; | |
} | |
.main-navigation ul li { | |
margin-right: 40px; | |
margin-bottom: 10px; | |
min-height: 30px; | |
} | |
.main-navigation ul a, | |
.main-navigation ul a:visited { | |
border: none; | |
color: $black; | |
font-size: 16px; | |
font-weight: 400; | |
line-height: 22px; | |
position: relative; | |
text-decoration: none; | |
text-transform: uppercase; | |
} | |
.main-navigation ul a:hover { | |
border-bottom: 3px solid; | |
} | |
.main-navigation ul ul { | |
display: none; | |
margin-top: 0px; | |
margin-left: 25px; | |
} | |
.main-navigation ul ul li{ | |
a{ | |
font-size: 14px; | |
text-transform: none; | |
padding: 0; | |
margin-bottom: 10px; | |
border-bottom: solid 4px transparent; | |
padding-bottom: 2px; | |
} | |
&:last-child{ | |
padding-bottom: 0; | |
a{ | |
margin-bottom: 0; | |
} | |
} | |
&:hover > a { | |
background: $neutral_200; | |
} | |
} | |
.main-navigation ul ul ul { | |
display: none; | |
margin-left: 25px; | |
} | |
.no-js .site-header-menu, | |
.site-header-menu.toggled-on { | |
display: block; | |
} | |
.site-header-menu.toggled-on { | |
margin-top: 10px; | |
} | |
.no-js .main-navigation ul, | |
.main-navigation ul .sub-menu.toggled-on { | |
display: block; | |
} | |
button.dropdown-toggle, | |
button.menu-button { | |
display: inline; | |
background-color: transparent; | |
border: 0; | |
-webkit-appearance: none; | |
-moz-appearance: none; | |
cursor: pointer; | |
content: ""; | |
} | |
button.dropdown-toggle { | |
width: 25px; | |
height: 25px; | |
position: absolute; | |
right: 15px; | |
margin-left: 10px; | |
padding: 2px; | |
} | |
.dropdown-toggle:after, | |
.dropdown-toggle.toggled-on:after { | |
font-size: 1rem; | |
} | |
.menu-button { | |
width: 25px; | |
height: 25px; | |
float: right; | |
padding: 0 !important; | |
font-size: 1.35rem; | |
margin-top: 25px; | |
padding: 5px 5px 5px 5px; | |
} | |
.main-navigation a:focus, | |
button.dropdown-toggle:focus, | |
button.menu-button:focus { | |
outline: 1px solid $black; | |
outline-offset: 2px; | |
} | |
.no-js .menu-button { | |
display: none; | |
} | |
/* Plus symbol to expand sub-menu on mobile */ | |
.dropdown-toggle:after { | |
content: "\002B"; | |
} | |
/* Minus symbol to collapse sub-menu on mobile */ | |
.dropdown-toggle.toggled-on:after { | |
content: "\2212"; | |
} | |
/* 'Hamburger' or bars to expand menu on mobile*/ | |
.menu-button:before { | |
content: "\f0c9"; | |
font-family: "Font Awesome 6 Free"; font-weight: 400; | |
} | |
/* Times (x) to collapse menu on mobile*/ | |
.menu-button.toggled-on:before { | |
content: "\f00d"; | |
font-family: "Font Awesome 6 Free"; font-weight: 400; | |
} | |
.dropdown-toggle:after, | |
.dropdown-toggle.toggled-on:after, | |
.menu-button:before, | |
.menu-button.toggled-on:before { | |
font-weight: bold; | |
} | |
/* Screen readers */ | |
.screen-readers { | |
position: absolute !important; | |
width: 1px; | |
height: 1px; | |
margin: -1px; | |
padding: 0; | |
border: 0; | |
word-break: normal !important; | |
overflow: hidden; | |
clip: rect(0 0 0 0); | |
} | |
/* Desktop media query */ | |
@media only screen and (min-width: 768px) { | |
button.menu-button { | |
display: none; | |
} | |
.menu-container { | |
padding-top: 0; | |
padding-bottom: 0; | |
padding-left: 0; | |
} | |
.site-header-menu { | |
display: block; | |
margin-left: 10px; | |
float: right; | |
//margin-top: 30px; | |
clear: none; | |
} | |
.main-navigation ul { | |
position: relative; | |
float: left; | |
} | |
.main-navigation ul li { | |
position: relative; | |
float: left; | |
margin: 0; | |
padding: 10px; | |
min-height: 0px; | |
} | |
.no-js .main-navigation ul ul, | |
.main-navigation ul ul { | |
position: absolute; | |
display: none; | |
top: 100%; | |
left: 0; | |
padding: 0; | |
z-index: 999; | |
background: $white; | |
border-radius: 15px; | |
padding: 25px; | |
} | |
.no-js .main-navigation ul ul li, | |
.main-navigation ul ul li { | |
float: none; | |
width: 175px; | |
padding: 0; | |
padding-bottom: 15px; | |
} | |
.main-navigation ul .has-sub-menu > li { | |
padding-right: 40px; | |
} | |
.no-js .main-navigation ul ul ul, | |
.main-navigation ul ul ul { | |
top: -1px; | |
left: 100%; | |
margin-left: 0; | |
margin-top: -5px; | |
} | |
ul.sub-menu .dropdown-toggle { | |
position: absolute; | |
right: 10px; | |
top: 4px; | |
} | |
/* Arrow down */ | |
.main-navigation ul .dropdown-toggle:after { | |
content: "\f078"; | |
font-family: "Font Awesome 6 Free"; font-weight: 400; | |
font-size: .75rem; | |
} | |
/* Arrow right */ | |
.main-navigation ul ul .dropdown-toggle:after { | |
content: "\f054"; | |
font-family: "Font Awesome 6 Free"; font-weight: 400; | |
font-size: .75rem; | |
} | |
/* Arrow up */ | |
.main-navigation ul .dropdown-toggle.toggled-on:after { | |
content: "\f077"; | |
font-family: "Font Awesome 6 Free"; font-weight: 400; | |
} | |
/* Arrow left */ | |
.main-navigation ul ul .dropdown-toggle.toggled-on:after { | |
content: "\f053"; | |
font-family: "Font Awesome 6 Free"; font-weight: 400; | |
} | |
.main-navigation ul .dropdown-toggle:after, | |
.main-navigation ul ul .dropdown-toggle:after, | |
.main-navigation ul .dropdown-toggle.toggled-on:after, | |
.main-navigation ul ul .dropdown-toggle.toggled-on:after { | |
font-weight: bold; | |
} | |
button.dropdown-toggle { | |
width: auto; | |
height: auto; | |
position: inherit; | |
right: auto; | |
} | |
.main-navigation ul li:hover > ul { | |
display: block; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment