I am trying to create an accessible navigation menu for a portfolio-style website. When the screen is less than a certain width (768px for this demo) the horizontal menu navigation disappears and is replaced with a 'burger'. The burger's parent div has a JavaScript onclick and onkeydown function so that when the burger is clicked or tapped, or a keyboard user focuses on it and uses presses spacebar or enter, a div 'sidenav' opens up from the side containing the vertical navigation menu.
However, if a keyboard user continues tabbing, the focus carries on down the page behind the navigation as if 'sidenav' was not there and when the tabbing eventually finds its way to the top of the sidenav, the first element it encounters is the close button and tabbing closes the menu, so there's no way of reaching the menu items.
So: Question 1: How can I trigger the focus to 'jump' to the newly opened navigation when the burger is keyed down?
Question 2: How can I make the 'close' button ignore tabbing and only work with the spacebar or enter key?
Here is a simplified version of my menu (you may need to go full screen to see the horizontal menu).
/* detect keyboard users */
function handleFirstTab(e) {
if (e.keyCode === 9) { // the "I am a keyboard user" key
document.body.classList.add('user-is-tabbing');
window.removeEventListener('keydown', handleFirstTab);
}
}
window.addEventListener('keydown', handleFirstTab);
/* Open Sidenav
-------------------*/
function openNav() {
let element = document.querySelector('ul.menucontent');
if (element.classList.contains('menucontent')) {
element.classList.remove('menu-a');
element.classList.add('menu-b');
};
let element3 = document.querySelector('div.sidenav');
let element4 = document.querySelector('.closebtn');
if (element3.classList.contains('sidenav')) {
element3.style.width = "350px";
element4.style.visibility = "visible";
};
document.getElementById('vmenu').focus();
}
function closeNav() {
let element = document.querySelector('ul.menucontent');
if (element.classList.contains('menucontent')) {
element.classList.remove('menu-b');
element.classList.add('menu-a');
};
let element3 = document.querySelector('div.sidenav');
let element4 = document.querySelector('.closebtn');
if (element3.classList.contains('sidenav')) {
element3.style.width = "0";
element4.style.visibility = "hidden";
};
}
// Toggle content
for (const selector of [".toggle-btn",]) {
const toggleButtons = [...document.querySelectorAll(selector)];
for (const toggleButton of toggleButtons) {
toggleButton.addEventListener('click', () => {
toggleButtons.filter(b => b !== toggleButton).forEach(b => {
b.nextElementSibling.classList.remove('reveal-content');
});
toggleButton.nextElementSibling.classList.toggle('reveal-content');
});
};
}
for (const selectorTwo of [".close-btn",]) {
const closeButtons = [...document.querySelectorAll(selectorTwo)];
for (const closeButton of closeButtons) {
closeButton.addEventListener('click', () => {
closeButton.parentElement.classList.toggle('reveal-content');
});
};
}
body.user-is-tabbing button > a:focus {
border: none;
}
body:not(.user-is-tabbing) a:focus,
body:not(.user-is-tabbing) button:focus,
body:not(.user-is-tabbing) input:focus,
body:not(.user-is-tabbing) select:focus,
body:not(.user-is-tabbing) textarea:focus {
outline: none;
}
.container-fluid,
.container {
margin-right: auto;
margin-left: auto;
width: 100%;
}
.d-block
.d-none {
display: none;
}
.sidenav {
height: 100%;
width: 0;
position: fixed;
z-index: 996;
top: 0;
left: 0;
background-color: #fff;
overflow-x: hidden;
transition: 0.5s;
padding: 1rem 0 0;
box-shadow: 0 2px 5px #acaaaa;
}
.trigram {
position: relative;
top: 0;
left: 0;
margin-bottom: 1rem;
padding: 0;
background: transparent;
z-index: 995;
width: 2rem;
}
.burger {
position: relative;
border-top: 0.15rem solid green;
border-bottom: 0.15rem solid green;
background: transparent;
height: 1.5rem;
width: 2rem;
}
.burger::after {
position: absolute;
content: "";
border-top: 0.15rem solid green;
top: 40%;
left: 0;
width: 2rem;
}
.sidemenu {
position: relative;
top: 5rem;
}
.mm ul {
list-style: none;
}
.mm li {
margin: 1rem 0;
padding: 0 0 0 1rem;
}
.mm .menucontent.menu-a {
display: none;
}
.mm .menucontent.menu-b {
display: flex;
display: -webkit-flex;
flex-direction: column;
justify-content: normal;
margin: 0 0 1rem;
padding: 0;
position: relative;
top: 0;
z-index: 997;
overflow-y: auto;
}
.closebtn {
border-bottom: none;
font-size: 2.25rem;
margin: 0;
position: absolute;
top: 2rem;
right: 2rem;
z-index: 998;
}
@media only screen and (min-width: 768px){
.d-none {
display: none;
}
.d-md-block {
display: block;
}
.trigram {
display: none;
}
.mm .menucontent.menu-a {
position: relative;
padding: 0;
margin: 0 auto;
white-space: nowrap;
display: flex;
}
.mm .menucontent.menu-a,
.mm .menucontent.menu-b {
flex-direction: row;
justify-content: center;
}
.mm li {
padding: 0 0.5rem;
}
.main-menu-container {
border-top: 2px solid green;
border-bottom: 2px solid green;
padding: 0.5rem 0;
margin: 1rem 0;
}
}
<div id="sidenav" class="sidenav">
<div id="closebtn" class="closebtn">
<a href="javascript:void(0)" onclick="closeNav()" onkeydown="closeNav()" role="button" tabindex="0" aria-label="close navigation">×</a>
</div>
<div id="vmenu" class="sidemenu d-md-none mm">
<nav aria-label="Main Navigation" class="menuouter ">
<ul class="menucontent menu-a" role="menubar">
<li class="item-101 default current active single top-level" role="none" tabindex="-1">
<a href="#" title="Side menu Home" class="icon-home">Side menu Home</a>
</li>
<li class="item-128 single" role="none" tabindex="-1">
<a href="#" title="Side menu page 2">Side menu page 2</a>
</li>
</ul>
</nav>
</div>
</div>
<div class="container-fluid menu-outer d-block d-md-none">
<div id="trigram" class="trigram" role="button" tabindex="0" aria-label="open navigation" aria-controls="sidenav" aria-haspopup="true" onclick="openNav()" onkeydown="openNav()">
<div class="burger" style="cursor:pointer" > </div>
</div>
</div>
<div class="container-fluid d-none d-md-block">
<div class="main-menu-container">
<div id="hmenu" class="row d-none d-md-block main-menu mm">
<nav aria-label="Main Navigation" class="menuouter ">
<ul class="menucontent menu-a" role="menubar">
<li class="item-101 default current active single top-level" role="none" tabindex="-1">
<a href="#" title="Horizontal menu Home" class="icon-home">Horizontal menu Home</a>
</li>
<li class="item-128 single" role="none" tabindex="-1">
<a href="#" title="Horizontal menu page 2">Horizontal menu page 2</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div>This is some text. It has a link in it: <a href="#">This is the first link</a></div>
<div>Here is some more text with more links. It has a link in it: <a href="#">This is the second link</a>. Integer mauris sem, convallis ut, consequat in, sollicitudin sed, leo.</div>
<div>Sed lacus velit, consequat in, ultricies sit amet, malesuada et, diam. Integer mauris sem, convallis ut, consequat in, sollicitudin sed, leo. <a href="#">This is the third link </a>Cras purus elit, hendrerit ut, egestas eget, sagittis at, nulla. Integer justo dui, faucibus dictum, convallis sodales, accumsan id, risus. Aenean risus. Vestibulum scelerisque placerat sem.</div>