Headings in HTML 5 and accessibility

Firstly, apologies for the much-delayed second round of my HTML 5 redesign. Two things delay it:

This description of headings was originally part of a post unveiling the part two redesign, but I’m splitting it out because there has been a lot of talk lately about headings in HTML 4 and 5. The redesign will be unveiled after my trip to Oslo next week.

Headings in HTML4

We all know these; there are six layers, h1 to h6. If you want more levels, you’re stuffed. There are arguments that more than six levels is somehow confusing; I think that’s an empty argument. Badly structured content is confusing, even if it has only two levels of heading. Conversely, some well-structured content might legitimately more levels and the language doesn’t allow for that.

Headings are very useful for search engines; it helps them “understand” content. They are also vital for screenreader users who can navigate via headings. In JAWS, for example, a user can hit H to go to the next heading, 1 to go to the next h1, 2 to go to the next h2 and so on. I thoroughly recommend watching Importance of HTML Headings for Accessibility, a video by a blind web developer who shows how screenreader users navigate using headings.

Opinions are divided about whether accessibility is better served by never having more than one h1 per page, whether “skipping” a level (from h2 to h4 with no intervening h3, for example) for consistency’s sake helps or hinders are all arguments that Henny Swan excellently summarises, so please comment there on those questions.

The problem with “hardcoded” headings is that they are hardcoded and can’t change according to context. The title of this whole blog post is presented by WordPress as a h2 on the home page, but as an h3 on a category page (as there is an h2 there saying “all posts in the HTML 5 category"). But the internal headings aren’t controlled by WordPress; I’m hardcoding them as h3. Unfortunately, they therefore remain at that level on the category pages, thereby destroying the hierarchy of headings.

Headings in XHTML 2

XHTML 2 has an elegant solution to this problem, and proposes an all-purpose h element as a general purpose heading. It gets its position in the hierarchy from how many levels of section elements wrap it.

Structured headings use the single h element, in combination with the section element to indicate the structure of the document, and the nesting of the sections indicates the importance of the heading. The heading for the section is the one that is a child of the section element.

So <body><section><h>Heading</h></section> is the same as an h1, and styleable with a CSS rule like section h {color:red;}.

<body><section><section><h>Heading</h></section></section> is the same as an h2, and styleable with a CSS rule like section section h {color:green;}.

Content Management systems can therefore take a lump of content (like this article) and wrap it in a section element and change the level of all the headings.

Headings in HTML 5

HTML 5 attempts to be backwards compatible, so it uses XHTML 2′s section element with the numbered headings from HTML 4 so that legacy content still works. That means that determining the “level” of any header is dependant on its explicit number (is it h1 or h-something else?) and how many levels of section surround it.

The algorithm is complex but tightly defined. My section demo page gives an idea of how this works, as well as styling examples. James Graham has written an outlining tool and I expect that tools such as Opera Dragonfly and Firebug will provide methods to work out "computed" levels of heading.

So in my redesign, I’m wrapping each article in a section element on a "category" page so that the hard-coded h3s ‘turn into’ h4s, which is a fine and dandy way to deal with this legacy content.


Current browsers don’t magically rejig the levels of headings, of course, as they have no knowledge of the section element, so just read that heading as the hard-coded h3. Those using screenreaders are not worse off and I’m future-proofing the document.

But the HTML 5 spec discourages mixing heading levels and sections:

Sections may contain headers of any rank, but authors are strongly encouraged to either use only h1 elements, or to use elements of the appropriate rank for the section’s nesting level.

Authors are also encouraged to explicitly wrap sections in elements of sectioning content, instead of relying on the implicit sections generated by having multiple heading in one element of sectioning content.

(This “discouraging” in a spec seems to me a disingenuous way of indicating that there is a kind of “HTML 5 transitional” spec wrapped up in the main spec. The code structures that are "discouraged" are very useful for transitioning legacy content, and the spec should say so in my opinion rather than daintily "discouraging".)

This says that authors of new content should really only use h1 for headings, and when they want sub-headings should do so by making another section. That’s all well and good, but what about screenreaders?

Current screenreaders would just see every heading on the page as a hard-coded h1, which destroys the ability to get a conceptual framework of the page or navigate it. In order to take advantage of the new HTML 5 way of computing the relative level of headings, screenreaders would need to incorporate the outlining algorithm. This isn’t too much to ask; they are user agents that consume and transform web content; the algorithm is open and published.

Let me put my cards on the table: if you correctly use a W3C specification, like this one, and obey WCAG, then I believe that your responsibility as a web author is done. I won’t delay using a technique because a user agent can’t deal with it (although I will try to give extra help where I can). Call me evil, but that’s how I feel today.

I’ve been worried enough to ask the HTML 5 top nobs to explicitly invite the main screenreader vendors to participate in the the development of the HTML 5 spec. Unfortunately, to my knowledge, we’ve seen no interest from them. Perhaps they don’t think their customers are interested; after all, they don’t even alert their users to HTML 4 elements like strong, em, b, i or del.

20 Responses to “ Headings in HTML 5 and accessibility ”

Comment by Tom

A few months ago I was at accessibility seminar where a blind user demo’ing a few sites and sites with more than one H1 completely threw him, and sites with the website heading as H1 were of irrelevance.

So now I use the page title, in this instance ‘Headings in HTML 5 and accessibility’ as the only H1.

Sorry, I’m just streaming in the youtube video link you posted, so I may just be repeating what is said there :)

Comment by Jim O'Donnell

Ditto what Tom’s saying – multiple h1 can screw up pages for people who rely on headings to navigate. A single, unique h1 on each page seems like the safest option for me.

Are there many web pages that require multiple h1 headings?

Comment by stuart

Hey Bruce,

Really enjoying these HTML 5 articles – they’ve prompted me to venture on to the new standard, and help with coming to grips with the huge spec document over at w3c.

Got a comment about the use of tags in HTML 5 – wouldn’t it be great if you could use either or ? Then you could have a new HTML5 compliant document with only elements (and ranking is properly sorted by section), or a transitional HTML4/5 document using .

Comment by Bruce

Tom, Jim: Henny’s got a good discussion about multiple H1s etc in HTML 4. I’ve commented over there, too.

Stuart; I’m glad you like the HTML 5 articles. I’m not evangelising it, but do want to try it out and then feed back any barking mad bits to the working group to influence the spec.

WordPress appears to have eaten part of your comment. If you’re saying “wouldn’t it be great if you could use normal h1-h6 headings or h1 in nested sections, then you can.

That’s exactly what I’m doing in this stage of my redesign; surrounding legacy content with new HTML structures.

But the spec “strongly encourages” you to use just H1 and sections for new content. That, in my opinion, is cleaner (and exactly like the XHTML 2 route, except you use h1 instead of h), but there is the problem screenreaders would also need to understand the outlining algorithm (or know what to do if told by the browser that this heading is equivalent to an h7) yet they seem to be sitting on the sidelines during the development of HTML 5.

Comment by Rijk

@Daniel: that http://www.h1debate.com site obviously isn’t interested into accessibilty much, making the tweeted texts almost unreadable. Or they are only interesting in a number, not in the reasoning behind people’s usage. Personally I think it makes no semantic sense to have two H1 headers right after each other. But level numbering is arbitrary, as long as you’re consistent there shouldn’t be problems for your users.

Comment by Paul

@Rijk I am the designer of the H1 Debate, and wanted to emphasise the poll first and the comments second, hence setting the opacity at 50%. If you hover over a tweet, it’s opacity increases to 100%.

Although the poll numbers are important, the comments make are the key to the debate. Each tweet is a vote after all, and I have had some great feedback from some of the Webs’ most respected designers.

Comment by davux

As the HTML 5 spec clarifies, it’s perfectly OK to use, say, a h2 as first-level title of its own section. Since there’s no h1, the outline algorithm will treat it as a first-level header. Yet, in “section”-unaware devices, the whole page structure will stay consistent and understandable.

So this approach is perfect for everyone, except the light frustration one can have as an author to type an h2 without prior h1 (although this is semantically unambiguous, as I just mentioned). I personally think I’ll be able to deal with this frustration, and this approach is a nice way to combine semantically correct code and consideration to HTML 5 unaware devices.

At this point, it’s also important to take into account that e.g. Braille readers are pretty expensive. Moreover, as you pointed out, some vendors are not very responsive, so maybe they won’t release compliant devices anytime soon. Let’s change our first-level (in a given section) h2′s to h1′s later, whenever everyone’s ready, it won’t be a lot of work anyway.