Search code examples
htmlaccessibilitywai-ariasemantic-markupoutliner

What's the best way to provide alternate headings for purposes of screen reader navigation?


I have been tasked with marking up a document whose visual headings have been authored something like:

  • Our paper discussing a variety of 2022 XYZ efforts
    • XYZ in 2022 within the fine arts sector
      • XYZ's 2022 progress in the fine arts sector summarized
      • Results of XYZ's 2022 progress by individual genre
        • Fine arts sector progress at XYZ within the craftsman movement
        • Fine arts sector progress at XYZ within the impressionist movement
        • Fine arts sector progress at XYZ within the postrecessional movement
    • XYZ in 2022 within the science sector
      • XYZ's 2022 progress in the science sector summarized
      • Results of XYZ's 2022 progress by individual branch
        • Science sector progress at XYZ within the chemistry field
        • Science sector progress at XYZ within the biology field
        • Science sector progress at XYZ within the phlogistonomy field
    • XYZ in 2022 within the advanced research sector
      • XYZ's 2022 progress in the research sector summarized
      • Results of XYZ's 2022 progress by endeavor
        • Research sector progress at XYZ within the public transit space
        • Research sector progress at XYZ within the quantum photonics space
        • Research sector progress at XYZ within the renewable mining space

My concern is that the way the headings are worded will make them tedious to navigate via screen reader. For example if I want to jump to the "impressionist movement" section I will have to listen to lots of repeated "XY within fine arts results" prefixes ahead of the actual info distinguishing each heading from the other.

This is not my content and I am not allowed to change the headings, nor will the authors. However, I have been given permission to adjust the markup so as to present a modified semantic "outline" view that differs from the visual one. Feedback welcome, but I think an outline like the following would be more useful to someone navigating by screen reader:

  • Our paper discussing a variety of 2022 XYZ efforts
    • Fine arts sector at XYZ in 2022
      • Summary of XYZ's 2022 progress
      • Results by individual genre
        • craftsman movement
        • impressionist movement
        • postrecessional movement
    • Science sector at XYZ in 2022
      • Summary of XYZ's 2022 progress
      • Results by individual branch
        • chemistry field
        • biology field
        • phlogistonomy field
    • Advanced research at XYZ in 2022
      • Summary of XYZ's 2022 progress
      • Results by endeavor
        • public transit space
        • quantum photonics space
        • renewable mining space

My question is, how do I accomplish this in a way that real-world screenreading utilities will pick up?

If I simply take each heading like:

<h4>Fine arts sector progress at XYZ within the impressionist movement</h4>

And add an aria-label with the shortened version like:

<h4 aria-label="impressionist movement">Fine arts sector progress at XYZ within the impressionist movement</h4>

Will that be an effective and appropriate solution? Is there a way I can test the results using something built into the OS like VoiceOver or ChromeVox, or do the paid utilities like JAWS behave quite a bit differently in this regard?


Solution

  • From a basic user experience (UX) perspective, you typically want to put the most important information first so that users can quickly scan the text and find what they need. Your example of finding "impressionist movement" is difficult even from a sighted perspective. My eyes have to scan the beginning of the text and sort of "filter" it out until I get to the text that is important, which is near the end of each heading. I find your second outline much easier to read/scan.

    That same concept applies for screen reader users too. If they can hear the important text first, then they can quickly move on if the text isn't what they're looking for.

    Screen readers users can quickly jump to various heading levels. If I knew that "impressionist movement" was heading level 4, <h4>, then I could press the 4 key to jump to the next heading level 4 so I wouldn't have to slog through every heading. That helps but I would still have to listen to the same repeated text at the beginning of the heading before I heard the important part at the end.

    aria-label works best when used on interactive elements, not static text. You'd have to test on a variety of screen readers to see if it is honored on headings. There's a "Practical Support for aria-label" document on the W3.org website that mentions that aria-label might not be honored for headings.

    • Don't use aria-label or aria-labelledby on any heading elements because it overrides them on NVDA, VoiceOver and Talkback. JAWS ignores them.

    If you want to go the route of providing alternative text for the heading, a better way would be to use visibly hidden screen reader text. This is done by defining a CSS class that fakes out the browser into not displaying the text but the text is really there so a screen reader user can still hear it. You can call the CSS class anything you want but a common name to use is sr-only. You can see a definition of that class at What is sr-only in Bootstrap 3?. (You don't have to use bootstrap to get that class. Just copy the CSS from that article.)

    So your code would have the current visible text from your first outline but you'd hide that text from screen readers via aria-hidden and then you'd have visibly hidden text that the sighted user can't see but the screen reader can. It would look something like this:

    <h4>
      <span aria-hidden="true">Fine arts sector progress at XYZ within the impressionist movement</span>
      <span class="sr-only">impressionist movement</span>
    </h4>