Getting Heading Levels Right - Including Here on DEV
Tags: a11y, webdev, meta, html
Published: 2019-10-22 16:59:58

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](https://dev.to/s_aitchison/5-key-takeaways-from-the-webaim-screen-reader-user-survey-59gj)). 

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`)
- Second section title (`h2`)
    - Sub-heading within section 2 (`h3`)
        - Minor heading relevant to this sub-section (`h4`)

## 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](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd), 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:

{% link https://dev.to/s_aitchison/psa-stop-hard-coding-heading-levels-in-your-react-components-2ekp %}

## 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](https://www.buymeacoffee.com/mgkZuRU) so I can keep making content* 🙂