During Hacktoberfest I spent some time searching for and helping with small accessibility issues in open source projects. One issue I saw coming up time and again was around inappropriate use of heading levels. It's a topic that's come up in comments on some of my posts before, and I feel like if we can shift our approach on heading levels, we can side step some of these a11y issues, and in some cases get a little SEO win too.
Why heading levels matter to accessibility
The most common way for screen reader users to parse your web content is to first navigate by heading level (as detailed in the latest WebAIM screen reader survey results).
This means they will use shortcut commands to scan your headings in order of their level - h1
s followed by h2
s and so on. This approach directly correlates to the way sighted users consume your web content - instead of scanning what looks like the most important headings, the screen reader infers the order of importance from the level of the heading tag used.
Sequential heading levels allow screen reader users to scan for content
A screen reader user, just like any other user, does not want to read every word of content on a page to find the key information they are looking for.
When a sighted user scans your page they internally process: page purpose → top level content → section content → more detailed content. They can quickly visually interpret the hierarchy of information on the page.
To facilitate the same behaviour for screen reader users, sequential headers can be used: h1
(page purpose) → h2
(top level content) → h3
(next level content).
We need to approach heading levels as an indicator of priority, not style
When speaking to other developers I often find that heading levels are considered an aspect of style. The fact that out-of-the-box browser behaviour results in h1
elements being bigger than h2
, and so on, serves to reinforce that point of view.
The result is quite often in web content you'll find an h1
followed by an h4
or some other non-sequential progression. As established above however, heading levels have a semantic purpose. While styling can easily be changed with CSS, semantics can't, and therefore we should shift our way of thinking about heading levels to centre the hierarchy of information on the page.
Every page needs an h1
I can't stress this enough! The h1
element announces what the topic of the current page is, and an indication of what can be found within. For screen reader users it clearly sets the context of the page - omitting it is like a sighted user having to scan a whole page of content just to find out what a page is meant to be about. Similarly, you should only ever have one h1
on your page, as there should be only one 'source of truth' in terms of what the page is for.
I would argue that even sighted users benefit from an h1
element on every page, but if you feel strongly otherwise, remember you can always position your h1
off-screen using CSS so it will be perceivable to screen reader users, but not sighted users.
A descriptive h1
will also benefit your SEO, as it helps crawlers understand your page's content - just like screen readers!
Nest remaining headers, in order of importance
After the h1
element, the next headings should occur in order, never increasing by more than one level. You may have multiple h2
s, h3
s etc, but for example an h3
should always be a descendant of an h2
.
I find the easiest way to think about it is like a tree of information:
Page title (h1
)
- Section title (
h2
)- Sub-heading within section (
h3
) - Sub-heading within section (
h3
)
- Sub-heading within section (
- Second section title (
h2
)- Sub-heading within section 2 (
h3
)- Minor heading relevant to this sub-section (
h4
)
- Minor heading relevant to this sub-section (
- Sub-heading within section 2 (
Learn to lint for issues
Mistakes with heading levels are easy to make, especially if you are working with a component-driven system like React. I'd strongly encourage you add a linting extension to your browser to allow you to highlight any inconsistencies in your heading levels easily. My favourite is the Axe Chrome Extension, which analyzes your page with one click and clearly reports and highlights where heading levels have gone awry.
Think about heading flexibility when creating reusable components
If you work with a component-based framework like React, remember to avoid hard-coding heading levels, so that they can be set according to the context they appear in. I wrote a little bit about this here:
PSA: Stop Hard-Coding Heading Levels in Your React Components
Suzanne Aitchison ・ Sep 23 '19 ・ 3 min read
A final note for writers here on DEV
Did you know that DEV automatically creates an h1
element for your post, containing the title you gave it? this means if you'd like to keep DEV accessibility-friendly, your first heading in your markdown content should be an h2
- i.e. ## First heading inside post
. From there, you can apply the same principles as detailed above to keep everything accessible!
Did you find this post useful? Please consider buying me a coffee so I can keep making content 🙂
Top comments (7)
There was a really great post on this recently that I recommend:
Stop using so many divs! An intro to semantic HTML
Ken Bellows ・ Mar 24 ・ 12 min read
Also you might find this page useful on my website Up Your A11y: Accessible Page Layouts
Adding a lint tool like Axe or Wave to your usual development browser and checking in with it regularly will give you lots of great pointers too.
Hope this helps!
I should also say, regardless of which HTML element your header is in, you can and should always consider it in connection with all other headers on the page - in terms of heading hierarchy you consider the page as a whole. Again, it helps a screen reader user scan the content the same way a sighted user would.
Using those additional semantic elements give your page other accessibility boosts, so definitely keep using them too!
Great article Suzanne, maybe we should change the markdown parser of the article editor to be smarter and disallow h1s...
Maybe it would be good even just in the guidance/"Things to know" page if we included some pointers 🤔
The editor guide is a possible place to put this but I feel having an automatism would make sense also for people that don't read it, or if the article gets in from other avenues (like RSS feeds and the API).
Would you consider opening an issue about this?
So much yes! What a great post, Suzanne - thanks for sharing your experiences!
Yes sorry I realised that after I posted - woops! Hopefully my other reply makes sense 🙃