Codementor Events

Getting keyboard-focusable elements | Zell Liew

Published Feb 05, 2020
Getting keyboard-focusable elements | Zell Liew

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. This article was originally posted on my blog. Sign up for my newsletter if you want more articles to help you become a better frontend developer.

Discover and read more posts from Zell Liew
get started