Summary

JAWS' implementation of the HTML5 outline algorithm is incorrect with IE and Firefox when the author explicitly specifies the heading levels. Fortunately, there is a relatively simple fix until JAWS finally fixes the bug.

Important update

JAWS 15 removed its broken implementation of the outline algorithm.

Author: Gez Lemon

The HTML5 outline algorithm and JAWS

The HTML5 outline algorithm should automatically expose the correct heading level depending on the structure of sectioning elements. The following section elements influence the outline algorithm:

The following example is marked up using just level-1 heading elements, and is reported correctly by JAWS using IE and Firefox.

HTML5 Outline using h1 elements
<h1>Main page title</h1>
<nav>
  <h1>Site navigation</h1>
  <ul>
    <li>Home</li>
    <li><a href="⋯">Quality Assurance</a></li>
    <li><a href="⋯">Articles Archive</a></li>
  </ul>
</nav>
<section>
  <h1>Recent Posts</h1>
  <article>
    <h1>HTML5 outline algorithm and headings</h1>
    <p>
      How to fix the bug with JAWS and the HTML5
      outline algorithm.
    </p>
    <aside>
      <h1>Publish date</h1>
      <time datetime="2013-05-10T14:59Z">
        Friday, 10th May 2013
      </time>
    </aside>
  </article>
  <article>
    <h1>Handling erratic behaviour with AT</h1>
    <p>
      Difficulties testing with erratic AT, 
      such as when outline algorithms go bad.
    </p>
    <aside>
      <h1>Views</h1>
      <p>This article has been viewed 3.7 times</p>
    </aside>
  </article>
</section>

Using JAWS with IE and Firefox, the heading levels are announced as:

With screen readers that do not yet support the HTML5 outline algorithm, such as NVDA and VoiceOver, all of the headings are announced as level-1 headings. The HTML5 outline algorithm allows authors to explicitly specify the heading levels so that they're supported by older user agents.

Explicitly specifying the heading levels
<h1>Main page title</h1>
<nav>
  <h2>Site navigation</h2>
  <ul>
    <li>Home</li>
    <li><a href="⋯">Quality Assurance</a></li>
    <li><a href="⋯">Articles Archive</a></li>
  </ul>
</nav>
<section>
  <h2>Recent Posts</h2>
  <article>
    <h3>HTML5 outline algorithm and headings</h3>
    <p>
      How to fix the bug with JAWS and the HTML5
      outline algorithm.
    </p>
    <aside>
      <h4>Publish date</h4>
      <time datetime="2013-05-10T14:59Z">
        Friday, 10th May 2013
      </time>
    </aside>
  </article>
  <article>
    <h3>Handling erratic behaviour with AT</h3>
    <p>
      Difficulties testing with erratic AT, 
      such as when outline algorithms go bad.
    </p>
    <aside>
      <h4>Views</h4>
      <p>This article has been viewed 3.7 times</p>
    </aside>
  </article>
</section>

This example now correctly reports the heading levels in screen readers that do not support the HTML5 outline algorithm, but are now reported incorrectly by JAWS. JAWS announces the level implied by the outline added to the explicitly specified level. The headings in this example are now announced by JAWS as:

JAWS calculates all heading levels within a section by adding the explicit heading level to the heading level calculated from the outline. This works if all headings within a section start with a level-1 heading, and then used in order without skipping a level in the section, but breaks if the levels are not reset for each section. If a level-3 heading element is defined in the first section element, JAWS announces it as a level-4 heading:

Level-3 sub-heading reported as level-4
<section>
  <h2>Recent Posts</h2>
⋯
  <h3>Sub-heading</h3>
⋯
</section>

Similarly, if a level is skipped, JAWS just adds that level to the current outline calculation. So a level-4 element in the first section element would be announced as a level-5 heading:

Skipping a heading level
<section>
  <h2>Recent Posts</h2>
⋯
  <h4>Sub-heading</h4>
⋯
</section>

Fixing the JAWS bug

Fortunately, the problem with JAWS can be solved using WAI-ARIA by applying the heading role and aria-level attribute on the heading elements that are reported incorrectly.

Using role="heading" with the aria-level attribute
<h1>Main page title</h1>
<nav>
  <h2 role="heading" aria-level="2">
    Site navigation
  </h2>
  <ul>
    <li>Home</li>
    <li><a href="⋯">Quality Assurance</a></li>
    <li><a href="⋯">Articles Archive</a></li>
  </ul>
</nav>
<section>
  <h2 role="heading" aria-level="2">
    Recent Posts
  </h2>
  <article>
    <h3 role="heading" aria-level="3">
      HTML5 outline algorithm and headings
    </h3>
    <p>
      How to fix the bug with JAWS and the HTML5
      outline algorithm.
    </p>
    <aside>
      <h4 role="heading" aria-level="4">
        Publish date
      </h4>
      <time datetime="2013-05-10T14:59Z">
        Friday, 10th May 2013
      </time>
    </aside>
  </article>
  <article>
    <h3 role="heading" aria-level="3">
      Handling erratic behaviour with AT
    </h3>
    <p>
      Difficulties testing with erratic AT, 
      such as when outline algorithms go bad.
    </p>
    <aside>
      <h4 role="heading" aria-level="4">
        Views
      </h4>
      <p>This article has been viewed 3.7 times</p>
    </aside>
  </article>
</section>

The heading elements are now announced correctly by all screen readers, including JAWS.

Category: Accessibility.

Comments

  1. [html5-outline-algorithm-jaws.php#comment1]

    You could do this entirely with scripting. The following jQuery would add the heading role and appropriate aria-level to all headings inside HTML5 sectioning elements.

    
    $("nav :header, section :header, article :header, aside :header").attr('role','heading').attr('aria-level',function() {
    	return $(this).prop('tagName').substr(-1);
    });
    

    Posted by Jared Smith on

  2. [html5-outline-algorithm-jaws.php#comment3]

    So, basically the JAWs developers implemented a new outlining algorithm without any kind of testing or concern for backwards compatibility?

    Posted by Janette on

  3. [html5-outline-algorithm-jaws.php#comment4]

    The changes suggested to the heading levels ends up making the headers less accurate to what they actually are. The article tag should have an h1 since that's the highest level header of that tag.

    How do the aria roles perform on both readers with <h1 role="heading" aria-level="3"> ?

    Posted by Devon Rathie-Wright on

  4. [html5-outline-algorithm-jaws.php#comment5]

    Hello Devon,

    The article element just represents a self-contained section of a page, so doesn't necessarily represent the major section for the whole document. In the example posted, the article elements are a series of summaries of recent posts, so should be sub-headings, rather than repeated level-1 headings for the whole page.

    <h1 role="heading" aria-level="3"> is exposed as a level-3 heading by AT that supports WAI-ARIA, and level-1 by AT that doesn't. <h3 role="heading" aria-level="3"> is exposed as a level-3 heading element by any AT that understands heading elements.

    Posted by Gez on

  5. [html5-outline-algorithm-jaws.php#comment8]

    For the people who do not like to include jQuery for all their browser-fixing needs, here is my go at adding the attributes in plain JavaScript:

    (function(a,l,e,v){for(;--a;)for(l=document.getElementsByTagName('h'+a),e=l.length;v=l[--e];v.setAttribute('role','heading'))v.setAttribute('aria-level',a)})(8);

    Kept it as short and self-contained as possible so you should be able to drop it into any page.

    Posted by Martijn on

  6. [html5-outline-algorithm-jaws.php#comment9]

    Great write up on the way to deal with this bug, Gez. It's interesting to note that this bug has been an issue since JAWS 12 (see http://www.accessibleculture.org/articles/2011/10/jaws-ie-and-headings-in-html5/). In correspondence I had with Freedom Scientific about a year ago they indicated an interest in fixing it for JAWS 14. Doesn't appear they were successful *sad*

    It doesn't help, I think, that the outline algorithm is a feature at risk and hasn't yet stabilised in the spec. Or that the implementation of the algorithm by tools like gsnedders' and Steve's bookmarklet aren't necessarily aligned with more recent implementations of the algorithm in the W3C's dev validator (see http://lists.w3.org/Archives/Public/public-html/2013Apr/0003.html). While JAWS' implementation is clearly wrong, things with the algorithm itself aren't so clear.

    Posted by Jason Kiss on

  7. [html5-outline-algorithm-jaws.php#comment10]

    So, basically the JAWs developers implemented a new outlining algorithm without any kind of testing or concern for backwards compatibility?

    Posted by Jeet on

  8. [html5-outline-algorithm-jaws.php#comment12]

    In order to satisfy screen readers and other assistive technologies, it is necessary to use the traditional/HTML 4 heading structure, and then to work around the JAWS bug by using ARIA to specify the heading level, overriding JAWS incorrect default behavior.We add role="heading" and aria-level as appropriate to the level of the heading in the outline. These additions tell ARIA-aware screen readers/browsers, such as JAWS with IE or Firefox, to report the correct level for the heading.

    Posted by Application on

Comments are closed for this entry.