Grabbing all tabbable / focusable elements in a document

3.6k Views Asked by At

I am improving accessibility in a web-app.

I would like to cycle through all potentially tabbable / focusable elements

I note that jQuery has its own pseudo-selector, :tabbable but this isn't native.

I've never used jQuery much and I'm in no hurry to start.

I also note that in these two blog posts:

the (similar) solutions look like:

const keyboardfocusableElements = document.querySelectorAll(
  'a[href], button, input, textarea, select, details, [tabindex]'
);

I'm guessing we might be able to add a few more items:

  • audio
  • button
  • canvas
  • details
  • iframe
  • input
  • select
  • summary
  • textarea
  • video
  • [accesskey]
  • [contenteditable]
  • [href]
  • [tabindex]

though perhaps some of these elements only become tabbable / focusable when they include the tabindex attribute...?

Sticking with the list immediately above (for now), leaves us with the following:

const tabbableElements = document.querySelectorAll(
  'audio, button, canvas, details, iframe, input, select, summary, textarea, video, [accesskey], [contenteditable], [href], [tabindex]'
);

which isn't terrible, but you'd be forgiven for thinking there might be something more elegant.

Is there a conciser approach to grabbing all potentially tabbable / focusable elements in a document?

Something like a CSS Level 4 pseudo-selector ? (I've not found anything along those lines...)

1

There are 1 best solutions below

14
Rounin On

It occurred to me I should head over to jQuery and see what they were doing for:

jQuery states:

Elements of the following type are focusable if they are not disabled: <input>, <select>, <textarea>, <button>, and <object>. Anchors are focusable if they have an href or tabindex attribute. <area> elements are focusable if they are inside a named map, have an href attribute, and there is a visible image using the map. All other elements are focusable based solely on their tabindex attribute and visibility.

So, the approach I'm going with is to find all the elements which satisfy the conditions above - and any other conditions I may choose to add - and ensure, manually, that each has an explicit tabindex attribute.

Then I can use:

document.querySelectorAll('[tabindex]');

to select all potentially tabbable / focusable elements.

I remain open to other approaches, but, although only semi-automated, this seems the most practical way forward I can come up with for now.