Alvaro Montoro
Alvaro Montoro

Reputation: 29715

Make screen reader ignore a section but read its focusable content

I have some code that looks more or less like this (reduced for example):

html {
  background: #eee;
}

section {
  border-radius: 4px;
  border: 1px solid #ccc;
  background: #fff;
  margin: 1em;
  padding: 1em;
}

[tabindex]:focus {
  outline: 1px dashed blue;
}
<section tabindex="0">
  <h1>
    Section 1
  </h1>
  <p>
    This section will be highlighted but it won't go inside as 
    nothing inside has tabindex. I don't want it to be read at all.
  </p>
</section>

<section tabindex="0">
  <h1>
    Section 2
  </h1>
  <p>
    This section will be highlighted and there is an element inside with 
    tabindex. I don't want the section to be read, but I want to read
    the focusable elements when they are focused.
  </p>
  <p tabindex="0">
    For example: this paragraph has tabindex. It should be read when focused.
  </p>
</section>

There are different sections that are highlighted when they gain focus because they have tabindex. This highlight is there to easily identify the section that the user is at any given moment.

Inside each of those sections there could be anything: text, html code, focusable content (either because it has tabindex or because it has interactive elements). This is a web component and I don't have control over what goes inside.

We have screen reader users and low vision users, they both use the keyboard to navigate and, for the latter, we want to help identify in which section they are (within a page with multiple section/cards) without impacting negatively the screen reader users.

When the section is highlighted, I'd like it to be only graphically (with the outline) but I don't want the screen reader to read its content, because if there is any interactive/focusable contente inside, it will be read twice and don't want duplicates.

For example: using a screen reader like ChromeVox or VoiceOver, when pressing the tab, the first section will be outlined and it will sound something like this:

[Section] Section 1. This section will be highlighted but it won't go inside as nothing inside has tabindex. I don't want it to be read at all.

Hitting the tab again, the second section will be outlined and it will sound something like:

[Section] Section 2. This section will be highlighted and there is an element inside with tabindex. I don't want the section to be read, but I want to read the focusable elements when they are focused. For example: this paragraph has tabindex. It should be read when focused.

Hitting the tab a third time will activate the last paragraph inside the section (it has a tabindex), and the screen reader will say:

For example: this paragraph has tabindex. It should be read when focused.

This scenario is not ideal because we are repeating content (remember the code above is an example, in reality is more than just that). When a section gains focus, it is read completely; and when the content inside gains focus, it is read again. The last sentence was read twice: when the section is active and when it is active itself.

I would want to get the following behavior:

  1. Press tab, and the first section is highlighted. Nothing is read.
  2. Press tab, and the second section is highlighted. Nothing is read.
  3. Press tab, and the last paragraph is highlighted AND it is read.

I tried getting to that behavior through different approaches:

html {
  background: #eee;
}

section {
  border-radius: 4px;
  border: 1px solid #ccc;
  background: #fff;
  margin: 1em;
  padding: 1em;
}

[tabindex]:focus {
  outline: 1px dashed blue;
}
<section tabindex="0" aria-hidden="true">
  <h1>
    Section 1
  </h1>
  <p>
    This section will be highlighted but it won't go inside as 
    nothing inside has tabindex. I don't want it to be read at all.
  </p>
</section>

<section tabindex="0" aria-hidden="true">
  <h1>
    Section 2
  </h1>
  <p>
    This section will be highlighted and there is an element inside with 
    tabindex. I don't want the section to be read, but I want to read
    the focusable elements when they are focused.
  </p>
  <p tabindex="0">
    For example: this paragraph has tabindex. It should be read when focused.
  </p>
</section>

I tried wrapping the whole content of the section into a div with aria-hidden="false", but it seems that the parent's aria-hidden="true" supersedes it.

Is there a way of achieving what I want?

Upvotes: 1

Views: 5312

Answers (2)

Adam
Adam

Reputation: 18855

Screen reader users don't need tabindex to navigate within text with their keyboard.

Only interactive elements (buttons, links, form elements, ...) may have tabindex. And you don't have to add a tabindex if you use a native interactive element (a[href] button, input, ...), only for custom controls (<div role="button" tabindex="0">click here</div>).

Focusable elements should not be inside another focusable element.

Screenreaders have mainly two navigation mode : the browse/reading mode (using usually arrow keys), and the focus/form mode (using tab key). A screen reader user will never use the tab key with the intent to read a non interactive text.

You also do not need to add an outline to currently read text as the screenreader would do it automatically in browse mode.

Upvotes: 6

Patrick H. Lauke
Patrick H. Lauke

Reputation: 152

short answer: stop adding tabindex everywhere. screen reader users navigate with reading keys, so there's no point doing whatever it is you're trying to do with making things focusable...

Upvotes: 5

Related Questions