Focus-trap
by csornmo
HTML
<button id="openNav">
Open Nav
</button>
<div id="container">
<button id="closeNav">
Close Nav
</button>
<nav>
<ul>
<li>
<a href="#">Page 1</a>
</li>
<li>
<a href="#">Page 2</a>
</li>
<li>
<a href="#">Page 3</a>
</li>
<li>
<a href="#">Page 4</a>
</li>
</ul>
</nav>
</div>
<button>
button outside
</button>
CSS
#container {
display: none;
position: absolute;
border: 2px solid #000;
margin: 1rem 0;
}
JavaScript
$('#openNav').click(function() {
$('#container').show();
});
$('#closeNav').click(function() {
$('#container').hide();
$('#openNav').focus();
});
///////////////////////////////////////////////////////////
/////////////////////// Focus-trap ///////////////////////
/////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
const container = document.querySelector('#container'); // <----- Fill in your div container here and its done
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
function getFocusable(context = 'document') {
return Array.from(context.querySelectorAll('button, [href], input:not([type="hidden"]), textarea, select, [tabindex]:not([tabindex="-1"])')).filter(function (el) { return !el.closest('[hidden]'); });
}
const focusableItems = getFocusable(container);
document.addEventListener("keydown", function (e) {
if ( window.getComputedStyle(container).display === "none") {
return;
}
if (e.keyCode === 9) { // Tab & Shift+Tab
const focusedItem = e.target;
const focusedItemIndex = focusableItems.indexOf(focusedItem);
if (e.shiftKey) {
if (!container.contains(e.target) || focusedItemIndex === 0) {
focusableItems[focusableItems.length - 1].focus();
e.preventDefault();
}
} else {
if (!container.contains(e.target) || focusedItemIndex == focusableItems.length - 1) {
focusableItems[0].focus();
e.preventDefault();
}
}
}
});