Martin
Martin

Reputation: 301

Accessibility: does `tabindex="-1"` mean the element is not visible to screenreaders (similar to `aria-hidden="true"`)

I have a webpage where a dialog <section role="dialog"> element opens on-top-of content, causing the elements/content underneath to be inaccessible.

While the dialog is open, all content underneath receives tabindex="-1" to keep the tab-focus within the dialog.

The content underneath also receives a CSS class that blurs the elements, and sets pointer-events to none so the elements are not clickable with a mouse, but these elements are still all present and visible in the DOM (they are NOT set to display: none).

Two questions:

  1. Do I also need to add aria-hidden="true" to all of these elements too?
    • I understand the content will no longer be focusable with the tab key, but I'm not sure if the screenreader will still attempt to read the content.
  2. If I am setting aria-hidden="true" on these elements, and later reverting to aria-hidden="false", will the screenreader pick-up that this change happened?
    • I'm worried that setting aria-hidden="true" means the screenreader will not consider the element again, even if I set it later to aria-hidden="false".
    • Do I need aria-live on the shared parent element (where both the dialog and content exist)?
    • Even with aria-live, would the screenreader consider elements that were previously set to aria-hidden="true"?

Note: the dialog is a form with a submit button. Sometimes it could include a Dismiss button, but not in every case. The dialog could be acting as a gate that requires submitting the form to continue.

Upvotes: 6

Views: 7894

Answers (1)

GrahamTheDev
GrahamTheDev

Reputation: 24825

Accessibility: does tabindex=“-1” mean the element is not visible to screenreaders (similar to aria-hidden=“true”)

tabindex="-1" means that an item is only focusable programatically.

aria-hidden="true" means that item is completely removed from the accessibility tree.

They may seem the same until you consider that a screen reader user may navigate by <h1> to <h6> (for example). Adding tabindex="-1" makes no difference as a heading is not focusable anyway whereas aria-hidden="true" is essentially the same as saying display: none and means that it cannot be accessed by a screen reader at all.

With that in mind the answers to your questions become simple:

Do I also need to add aria-hidden="true" to all of these elements too?

Yes you do need to add aria-hidden="true" due to the fact that people may still try to navigate via Headings, Links etc. which aren't focusable anyway but can still be accessed via the virtual cursor.

If I am setting aria-hidden="true" on these elements, and later reverting to aria-hidden="false", will the screen reader pick-up that this change happened?

Yes a screen reader will have no problem with this. You do not need anything like aria-live in order to let the screen reader know the changes. In fact if you added aria-live you would make things less accessible as it would announce every time a change is made to the DOM in that whole section.

What do you need to consider

Managing focus - when you close the dialogue make sure that focus reverts to the button that opened it as that is expected behaviour. (make sure you do this after you make the parent / item aria-hidden="false" otherwise it may cause unexpected behaviour)

Esc to close - make sure the Escape key closes the dialogue.

How to structure a page for ease

An easy way to achieve all of this (if you are able to restructure everything) is to add all of your dialogues outside of the main content (you may get a warning that 'all items should be contained by landmarks' when running your site through an accessibility checker but ignore that guideline as your dialogue should not be accessible when the page loads anyway).

e.g.

<header aria-hidden="false"></header>
<main aria-hidden="false"></main>
<footer aria-hidden="false"></footer>
<section class="dialogue" role="dialogue" aria-hidden="true"></section>

toggles to

<header aria-hidden="true"></header>
<main aria-hidden="true"></main>
<footer aria-hidden="true"></footer>
<section class="dialogue" role="dialogue" aria-hidden="false"></section>

This way you only have 4 items that you need to add / toggle aria-hidden on so maintainability is easy.

Also for forward compatibility you may consider using the <dialogue> element

Upvotes: 10

Related Questions