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();
      }
    }
  }
});