Getting keyboard-focusable elements

29th Jan 2020

If you create JavaScript widgets, one of the key parts to accessibility is managing focus.

To manage focus, you need to find keyboard-focusable elements.

When you know the contents

It’s easy to find keyboard-focusable elements if you know the contents of the element beforehand.

For example, I know the focusable elements in this modal are <input> and <button>.

Modal with two inputs and one button.

I can get the focusable elements with querySelectorAll.

const focusableElements = [...modal.querySelectorAll('input, button')]

When you don’t know the contents

It’s harder to find keyboard-focusable elements if you don’t know the content beforehand.

After some research, I realised you could only focus on these elements with a keyboard:

  1. <a>
  2. <button>
  3. <input>
  4. <textarea>
  5. <select>
  6. <details>
  7. Elements with tabindex set to 0
  8. Elements with tabindex set to a positive number

We can get all keyboard-focusable elements with the following querySelectorAll. It looks a little complicated, but there’s no other way to include everything:

const keyboardfocusableElements = document.querySelectorAll(
  'a, button, input, textarea, select, details, [tabindex]:not([tabindex="-1"])'
)

Some elements (like button) can be disabled. Disabled elements are not focusable. We can remove these elements with filter.

const keyboardfocusableElements = [...document.querySelectorAll(
  'a, button, input, textarea, select, details, [tabindex]:not([tabindex="-1"])'
)]
  .filter(el => !el.hasAttribute('disabled'))

Turning it into a function

This querySelectorAll code is hard to read. We can put the entire thing into a function to make it more understandable.

/**
 * Gets keyboard-focusable elements within a specified element
 * @param {HTMLElement} [element=document] element  
 * @returns {Array}
 */
function getKeyboardFocusableElements (element = document) {
  return [...element.querySelectorAll(
    'a, button, input, textarea, select, details,[tabindex]:not([tabindex="-1"])'
  )]
    .filter(el => !el.hasAttribute('disabled'))
}

Useful JavaScript functions

I started keeping snippets of JavaScript functions I find useful in a Git repository. It’s tiny now though. I’ll add more to it as I go along.

Hope you find it useful.

If you have any suggestions to add to this repo, please let me know!

Thanks for reading. Did this article help you out? If it did, I hope you consider sharing it. You might help someone else out. Thanks so much!

Hold on while i sign you up…

🤗
Woohoo! You’re in!
Now, hold on while I redirect you.