The heading structure of a web page is like its table of contents. It gives people who can’t see your page a way to navigate it without reading everything.
To be clear, by ‘heading structure’ in this post, I mean the heading elements in your HTML: <h1>
to <h6>
. These elements can be strongly intertwined with what they look like, but for our purposes it is the markup that matters.
The best analogy I’ve been able to come up with for heading structures, is the feature in Microsoft Word that lets users generate a table of contents automatically. It is used a lot by all kinds of people, in all kinds of environments (in long corporate documents, but also in academia). If you’ve set document headings correctly, it lists all sections and subsections. It even remembers, and updates, which page they are on.
Example of the automagic table of contents feature in Pages. It even lets you select which heading levels to include!
All websites have this too, as a similar feature is built into most screenreaders. In VoiceOver, for example, users can press a button to see a list of all headings and use this to navigate a page. In fact, this is a common way for screenreader users to get around your page without reading everything.
The headings feature in action on Wikipedia. Note that Wikipedia also lists the headings explicitly, with section numbering.
Only use headings to identify sections
To let users get the best navigate-by-headings experience, only use heading elements for content that actually identifies a section. Ask ‘would this be useful in my table of contents?’, and if the answer is no, best choose a different HTML element. This way, only table of contents material makes it into your heading structure.
For this reason, by the way, I recommend to avoid having headings be part of user generated content (as in: content added not by content specialist, but by users of your site). If you offer Markdown for comments, for example, headings in those comments could mess with the usability of your heading structure.
If you choose something to be a header, make sure it describes the section underneath it. This can be hard to get right, you might have great puns in your headings, or maybe they were written by a SEO expert.
Visually hidden headings
Not all sections have headings, often the visual design makes it clear that something is a distinct piece of content. That’s great, but it doesn’t have to stop a section from also showing up in your table of contents. Hidden headings to the rescue!
A hidden heading is one that is ‘visually hidden’, this is content that is not visual on screen, but it exists in your markup and screenreaders can use it:
<h2 class="visually-hidden">Contact information</h2>
<!-- some content that looks visually a lot like contact
information, with icons and a receptionist stock
photo that makes it all very obvious-->
(More about CSS to visually hide)
The heading goes into your virtual table of contents, but it is not visible on screen.
Note that visible headings are much preferred to hidden headings. There are two problems in particular with hidden headings:
- Like with other hidden content, it can easily be forgotten about by your future self or the next team member. Hidden content that is not up to date with the visible content is unhelpful, so it is a bit of a risk.
- Serving slightly different content may cause confusing conversations, for example if an AT user and a sighted user discuss a page and only one of them knows that there is a heading.
‘Don’t skip heading levels’
Although WCAG 2 does not explicitly forbid skipping heading levels, and this is controversial, I would say it is best not to skip heading levels.
If a contract has clause 2.4.2, it would be weird for there not to be a 2.4 — the former is a subclause of the latter. It would be weird for the subclause to exist without the main clause.
The most common reason why people skip headings is for styling purposes: they want the style that comes with a certain heading and that happens to be the wrong level for structural purposes. There are two strategies to avoid this:
- have agreement across the team about how heading levels work
- use
.h1
,.h2
,.h3
classes, so that you can have correct heading levels, but style them however you like
The former is what I prefer, on many levels, but if it is a choice between weird CSS and happy users, that’s an easy one to make.
Automatically correct headings
The outline algorithm mentioned in HTML specifications is a clever idea in theory. It would let you use any headings you’d like within a section of content; the browser would take care of assigning the correct levels. Browsers would determine these levels by looking at ‘sectioning elements’. A sectioning element would open a new section, browsers would assume sections in sections to be subsections, and headings within them lower level headings.
There is no browser implementing the outline algorithm in a way that the above works. One could theoretically have automated heading levels with clever React components. I like that idea, although I would hesitate adding it into my codebases. That leaves us with manually choosing plain old headings level, from 1 to 6.
Conclusion
Heading structures give screenreader users and others a table of contents for our sites. By being conscious of that, we can make better choices about heading levels and their contents.
Comments, likes & shares (108)
Michael Hastrich, Kev, jameschurchman, Gaël Poupard, Accessabilly, Jon Gibbins, , krista sarginson, KseniaBlake, Bʀᴇᴛᴛ Jᴀɴᴋᴏʀᴅ, Sara, Damion Armentrout, John F Croston III, Wes Oudshoorn, Bram Nijmeijer, Rainer Martínez, Robbert, Katrina Voll, Bart Declercq, Eric Eggert, Dennis Lembrée 😸, Cantilever, Sarah Federman, Mathijs, Matsuko, David Dzumba, Dan, Gijs Veyfeyken, Sheri Richardson, Steve Lee, atilla, Rufus Witt, Koen Cornelis, Hannah Milan, Meagan Eller, Anith ✨, Sarah L. Fossheim (they/them), Yuan Gao, David Woodbridge (VA), Who me?, Arthur V Rodrigues, Marijke Luttekes, Simon R Jones 💙, Jasper Moelker 🔋🌳🇪🇺, Alicia Jarvis (She/Her/Hers), CPACC, CSM 🇨🇦, Devessier, Tim Kraut, Birkir Gunnarsson, Fynn Becker, Ana Tudor 🐯, Yakim, Peter Antonius, Jan Skovgaard, W3Cx, W3C Developers, Eddy Tran, Peyton Chance, Bogdan Cerovac, Accessabilly, Molly Brower, Josh Buchea, Johnny Taylor, Marc Friederich and JSConf Budapest liked this
Michael Hastrich, Jasha , Scott O'Hara, , =accessibility, Jon Gibbins, Marco Zehe, Damion Armentrout, Peter Armstrong, Brian J. Perdue, Fronteers, Matsuko, David Woodbridge (VA), Marco Zehe, Who me?, Alicia Jarvis (She/Her/Hers), CPACC, CSM 🇨🇦, atilla, Marco Zehe, Steve Lee, Sarah L. Fossheim (they/them), Gijs Veyfeyken, Eric Eggert, MsT, Geoff Shang, W3Cx, Sarah Van O..., Amy Mason (she), Eddy Tran, Josh Buchea and JSConf Budapest reposted this
✏️ Heading structures are tables of contents hiddedevries.nl/en/blog/2018-0…
toot.cafe/@Hdv/100657475…
#accessibility #a11y
>Conclusion
>Heading structures give screenreader users and others a table of contents for our sites. By being conscious of that, we can make better choices about heading levels and their contents.
hiddedevries.nl/en/blog/2018-0…
Instead of looking at whole pages only, can #PatternLibraries already be tested for #A11y & how? — by @hdv :
buff.ly/2vZRjuK
#DesignSystems
Instead of looking at whole pages only, can #PatternLibraries already be tested for #A11y & how? — by @hdv :
buff.ly/2vZRjuK
#DesignSystems
hiddedevries.nl/en/blog/2018-0…
This week, somebody proposed to replace HTML, CSS and JavaScript with just one language, arguing “they heavily overlap each other”. They wrote the separation between structure, styles and interactivity is based on a “false premise“. I don’t think it is. In this post, we’ll look at why it is good that HTML, CSS and JS are separate languages.
I’m not here to make fun of the proposal, anyone is welcome to suggest ideas for the web platform. I do want to give an overview of why the current state of things works satisfactorily. Because, as journalist Zeynep Tefepkçi said, quoted by Jeremy Keith:
On a sidenote: the separation between structure, style and interactivity goes all the way back to the web’s first proposal. At the start, there was only structure. The platform was for scientists to exchange documents. After the initial idea, a bunch of smart minds worked years on making the platform to what it is and what it is used for today. This still goes on. Find out more about web history in my talk On the origin of cascades (video), or Jeremy Keith and Remy Sharpe’s awesome How we built the World Wide Web in 5 days.
Some user needs
Users need structure separated out
The interesting thing about the web is that you never know who you’re building stuff for exactly. Even if you keep statistics. There are so many different users consuming web content. They all have different devices, OSes, screen sizes, default languages, assistive technologies, user preferences… Because of this huge variety, having the structure of web pages (or apps) expressed in a language that is just for structure is essential.
We need shared structure so that:
All of these users rely on us writing HTML (headings, semantic structure, autocomplete atributes, lang attributes, respectively). Would we want to break the web for those users? Or, if we use the JSON abstraction suggested in the aforementioned proposal, and generate DOM from that, would it be worth breaking the way developers are currently used to making accessible experiences? This stuff is hard to teach as it is.
Even if we would time travel back to the nineties and could invent the web from scratch, we’d still need to express semantics. Abstracting semantics to JSON may solve some problems and make some live’s easier, but having seen some attempts to that, it usually removes the simplicity and flexibility that HTML offers.
Users need style separated out
Like it is important to have structure separated out, users also need us to have style as a separate thing.
We need style separated out, so that:
Users need interactivity separated out
Some users might even want (or have) interactivity separated out, for instance if the IT department of their organisation turned the feature company-wide. Some users have JavaScript turned off manually. These days, neither are common at all, but there are still good reasons to think about what your website is without JavaScript, because JavaScript loss can happen accidentally.
We need interactivity separated out, because:
Existing abstractions
None of this is not to say it can’t be useful to abstract some parts of the web stack, for some teams. And people already do this, en masse, there is plenty of choice.
On the markup end of things, there are solutions like Sanity’s Portable Text that defines content in JSON, so that it can be reused across many different “channels”. This is a format for storing and transferring data, not for displaying it on a site. Because before you display it anywhere, you’d write a template to do that, in HTML.
For CSS there are extensions like Sass and Less, utility-first approaches like Tailwind.
As for JavaScript: there are numerous abstractions that make some of the syntax of JavaScript easier (jQuery, it its time), that help developers write components with less boilerplate (like Svelte and Vue) and that help teams make less programmatically avoidable mistakes (TypeScript).
I don’t use any of these abstractions for this site, or most others I work on, but many are popular with teams building complex websites happily do.
We’re very lucky that all of these abstract things that are themselves simple (ish) building stones: HTML, CSS and (to a different extent) JavaScript. With abstractions, individual teams and organisations can separate their concerns differently as they please, without changing the building blocks that web users rely on.
Conclusion
The separation between HTML, CSS and JavaScript as it currently is benefits web users. It does this in many ways that sometimes only become apparent after years (CSS was invented 25 year ago, when phones with browsers did not yet exist, but different
media
were already taken into account). It’s exciting to abstract parts of the web and remodel things for your own use case, but I can’t emphasise enough that the web is for people. Well written and well separated HTML and CSS is important to their experience of it.