ever and ran it through NVDA.
<!-- Don't do this -->
<section aria-label="Is this the section label?" aria-labelledby="is_this_the_label">
<h1>Or is this the section label?</h1>
<p id="is_this_the_label">Only ever use one at a time.</p>
</section>
This is the order of priority that NVDA gave to the various labeling methods from strongest to weakest:
aria-labelledby
aria-label
Adding section labels to our example layout
For a long time, I used headings as the only means of labeling sections. The poor multi-lingual support provided by aria-label
scared me; and aria-labelledby
was far too cumbersome to be my primary labeling method. We run into a bit of an issue though if we use only headings to label sections. I’ll show you what I mean.
<style>
.visually-hidden {
position: absolute;
opacity: 0;
pointer-events: none;
}
</style>
<body>
<header>
<a href="/" title="Go to home page">
<img src="logo.png" alt="Site logo">
</a>
<nav>
<h2 class="visually-hidden">Primary</h2>
<ul>
<li><a href="#">Primary nav</a></li>
<li><a href="#">Primary nav</a></li>
<li><a href="#">Primary nav</a></li>
<li><a href="#">Primary nav</a></li>
</ul>
</nav>
<form role="search" aria-label="site">
<label>
<span>Search</span>
<input type="search"/>
</label>
<button type="submit">Submit</button>
</form>
</header>
<nav>
<h2 class="visually-hidden">Secondary</h2>
<ul>
<li><a href="#">Secondary nav</a></li>
<li><a href="#">Secondary nav</a></li>
<li><a href="#">Secondary nav</a></li>
<li><a href="#">Secondary nav</a></li>
<li><a href="#">Secondary nav</a></li>
</ul>
</nav>
<main>
<article>
<h1>Main article heading</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quae sunt igitur communia vobis cum antiquis, iis sic utamur quasi concessis; Nihil acciderat ei, quod nollet, nisi quod anulum, quo delectabatur, in mari abiecerat. Unum est sine dolore esse, alterum cum voluptate. Laboro autem non sine causa; Theophrasti igitur, inquit, tibi liber ille placet de beata vita? Nihil opus est exemplis hoc facere longius. Duo Reges constructio interrete. Graecum enim hunc versum nostis omnes Suavis laborum est praeteritorum memoria. Haec et tu ita posuisti, et verba vestra sunt.</p>
<h2>Article secondary heading</h2>
<p>Nos commodius agimus. A mene tu? Tantum dico, magis fuisse vestrum agere Epicuri diem natalem, quam illius testamento cavere ut ageretur. Tenesne igitur, inquam, Hieronymus Rhodius quid dicat esse summum bonum, quo putet omnia referri oportere? Nihilo beatiorem esse Metellum quam Regulum. Sed quanta sit alias, nunc tantum possitne esse tanta. Philosophi autem in suis lectulis plerumque moriuntur. Esse enim, nisi eris, non potes.</p>
<p>Sunt enim quasi prima elementa naturae, quibus ubertas orationis adhiberi vix potest, nec equidem eam cogito consectari. Id Sextilius factum negabat. Quorum sine causa fieri nihil putandum est. Quae autem natura suae primae institutionis oblita est?</p>
</article>
</main>
<aside>
<h2 class="visually-hidden">Sidebar</h2>
<section>
<h3>Share</h3>
<ul>
<li><a href="#">Facebook</a></li>
<li><a href="#">Twitter</a></li>
<li><a href="#">Email</a></li>
</ul>
</section>
<section>
<h3>Recommended</h3>
<ul>
<li>
<article>
<h4><a href="#">Related article</a></h4>
<p>Article description</p>
</article>
</li>
<li>
<article>
<h4><a href="#">Related article</a></h4>
<p>Article description</p>
</article>
</li>
</ul>
</section>
</aside>
<footer>
<ul>
<li><a href="#">Footer link</a></li>
<li><a href="#">Footer link</a></li>
<li><a href="#">Footer link</a></li>
<li><a href="#">Footer link</a></li>
<li><a href="#">Footer link</a></li>
</ul>
</footer>
</body>
If we look at our heading structure now, it will look like this (italics = visually hidden; bold = visible):
-
Primary [nav]
Secondary [nav]
Main article heading
Article secondary heading
Sidebar
Share
Recommended
Related article
Related article
Notice that our
heading isn’t at the top of the list? It really doesn’t feel right having two
headings above the
heading.
This form of heading structure is actually allowed by the W3C so it doesn’t count as an accessibility fail. I still think that this is a pretty bad UX for screen reader users though. It is not a logical progression from
to
. It makes the most sense if the first heading you encounter on the page is a
then progress into
then
and so on.
Making Heading 1 be the first heading
For a very long time, I thought the absolute best way to handle this conundrum was to make the
visually hidden and have it be the very first piece of content on the page. The thing that everyone thinks is the
actually becomes a
.
This is what that sort of structure looks like in practice:
<style>
.visually-hidden {
position: absolute;
opacity: 0;
pointer-events: none;
}
</style>
<!-- Don't do this -->
<body>
<header>
<h1 class="visually-hidden">Main article heading</h1>
<a href="/" title="Go to home page">
<img src="logo.png" alt="Site logo">
</a>
<nav>
<h2 class="visually-hidden">Primary</h2>
<ul>
<li><a href="#">Primary nav</a></li>
<li><a href="#">Primary nav</a></li>
<li><a href="#">Primary nav</a></li>
<li><a href="#">Primary nav</a></li>
</ul>
</nav>
<form role="search" aria-label="site">
<label>
<span>Search</span>
<input type="search"/>
</label>
<button type="submit">Submit</button>
</form>
</header>
<nav>
<h2 class="visually-hidden">Secondary</h2>
<ul>
<li><a href="#">Secondary nav</a></li>
<li><a href="#">Secondary nav</a></li>
<li><a href="#">Secondary nav</a></li>
<li><a href="#">Secondary nav</a></li>
<li><a href="#">Secondary nav</a></li>
</ul>
</nav>
<main>
<article>
<h2><span class="visually-hidden">Body:</span> Main article heading</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quae sunt igitur communia vobis cum antiquis, iis sic utamur quasi concessis; Nihil acciderat ei, quod nollet, nisi quod anulum, quo delectabatur, in mari abiecerat. Unum est sine dolore esse, alterum cum voluptate. Laboro autem non sine causa; Theophrasti igitur, inquit, tibi liber ille placet de beata vita? Nihil opus est exemplis hoc facere longius. Duo Reges constructio interrete. Graecum enim hunc versum nostis omnes Suavis laborum est praeteritorum memoria. Haec et tu ita posuisti, et verba vestra sunt.</p>
<h3>Article secondary heading</h3>
<p>Nos commodius agimus. A mene tu? Tantum dico, magis fuisse vestrum agere Epicuri diem natalem, quam illius testamento cavere ut ageretur. Tenesne igitur, inquam, Hieronymus Rhodius quid dicat esse summum bonum, quo putet omnia referri oportere? Nihilo beatiorem esse Metellum quam Regulum. Sed quanta sit alias, nunc tantum possitne esse tanta. Philosophi autem in suis lectulis plerumque moriuntur. Esse enim, nisi eris, non potes.</p>
<p>Sunt enim quasi prima elementa naturae, quibus ubertas orationis adhiberi vix potest, nec equidem eam cogito consectari. Id Sextilius factum negabat. Quorum sine causa fieri nihil putandum est. Quae autem natura suae primae institutionis oblita est?</p>
</article>
</main>
<aside>
<h2 class="visually-hidden">Sidebar</h2>
<section>
<h3>Share</h3>
<ul>
<li><a href="#">Facebook</a></li>
<li><a href="#">Twitter</a></li>
<li><a href="#">Email</a></li>
</ul>
</section>
<section>
<h3>Recommended</h3>
<ul>
<li>
<article>
<h4><a href="#">Related article</a></h4>
<p>Article description</p>
</article>
</li>
<li>
<article>
<h4><a href="#">Related article</a></h4>
<p>Article description</p>
</article>
</li>
</ul>
</section>
</aside>
<footer>
<ul>
<li><a href="#">Footer link</a></li>
<li><a href="#">Footer link</a></li>
<li><a href="#">Footer link</a></li>
<li><a href="#">Footer link</a></li>
<li><a href="#">Footer link</a></li>
</ul>
</footer>
</body>
Now we have a document outline that looks like this (italics = visually hidden; bold = visible):
Main article heading
Primary [nav]
Secondary [nav]
Body: Main article heading
Article secondary heading
Sidebar
Share
Recommended
Related article
Related article
This mostly feels right. The
is at the top and it all flows down perfectly with the
elements representing major page sections and the
elements representing sub sections. The main awkward bit is that the actual
and the thing that everyone thinks is a
are essentially duplicates of one another.
It wasn’t until I wrote up the first version of this article, had it nearly published, then had it thrown out the window, that I started to think differently. I talked with two accessibility consultants about the issue. They both agreed that, though this is a clever technical solution to the problem, it detracts from the experience of the very people that it is trying to help.
The issue is that when every other website in the world places the
heading at the top of the main content area, that is what screen reader users come to expect. When your site is the special snowflake that does things differently, it confuses screen reader users and it takes them some time to figure out how your heading structure is supposed to work.
So, with that in mind, I’ve settled on a new method for handling the labeling of sectioning elements. Basically, any time I would have used a visually hidden heading, I would use an aria-label
attribute now instead. If the site has a large non-native speaking audience, I would use aria-labelledby
instead of aria-label
.
Concerns with the simplified outline algorithm spec
If the simplified outline algorithm is approved in its current state, we will actually need to start structuring our sites like the visually hidden
example anyway (just replace the
,
and
elements with
elements).
The original spec aimed to create the outline through the labeling of sectioning elements. This new spec is clearly aimed at trying to create the outline purely through heading levels. The algorithm basically calculates the heading level based on the number of ancestor sectioning elements a heading has plus the heading’s base heading level value. It’s a bit more nuanced than that in the spec, but that is the general idea of how it works in simple terms.
The simplified algorithm currently makes no mention of aria-label
or aria-labelledby
. This means that those attributes will not help contribute to the document outline that the simplified algorithm generates. With a lack of aria-label
support, this would mean labeling a sectioning element with aria-label
could easily lead to skipped heading levels deeper in the tree.
<!-- Simplified algorithm skipped heading levels issue -->
<body>
<main>
<h1>Primary heading for the page</h1> <!-- interpreted as <h1> -->
<p>This is some content</p>
</main>
<!-- sectioning elements increase heading levels -->
<aside aria-label="Side bar"> <!-- aria-label does not contribute -->
<section>
<h1>Share</h1> <!-- interpreted as <h3> -->
<ul>
<!-- list of social media links -->
</ul>
</section>
<section>
<h1>Recommended articles:</h1> <!-- interpreted as <h3> -->
<ul>
<!-- list of recommended articles -->
</ul>
</section>
</aside>
</body>
The simplified spec also considers it invalid to:
It does, however, allow for there to be more than one level 1 heading at the root of the document, which I find very odd and bad for accessibility (though my concern about this seems to have been ignored).
I have voiced the issues I have with the spec and proposed possible solutions in the GitHub discussion.
For the moment, it is still best to use aria-label
and/or aria-labelledby
attributes instead of visually hidden headings to label sectioning elements. It isn’t worth diminishing the experience of our present day users for the sake of a spec that hasn’t even been finalized or accepted yet.
Using aria on the example layout sectioning elements
Using aria-label
This is what the HTML structure looks like if we use aria-label
attributes to label the sectioning elements:
<body>
<header>
<a href="/" title="Go to home page">
<img src="logo.png" alt="Site logo">
</a>
<nav aria-label="Primary">
<ul>
<li><a href="#">Primary nav</a></li>
<li><a href="#">Primary nav</a></li>
<li><a href="#">Primary nav</a></li>
<li><a href="#">Primary nav</a></li>
</ul>
</nav>
<form role="search" aria-label="site">
<label>
<span>Search</span>
<input type="search"/>
</label>
<button type="submit">Submit</button>
</form>
</header>
<nav aria-label="Secondary">
<ul>
<li><a href="#">Secondary nav</a></li>
<li><a href="#">Secondary nav</a></li>
<li><a href="#">Secondary nav</a></li>
<li><a href="#">Secondary nav</a></li>
<li><a href="#">Secondary nav</a></li>
</ul>
</nav>
<main>
<article>
<h1>Main article heading</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quae sunt igitur communia vobis cum antiquis, iis sic utamur quasi concessis; Nihil acciderat ei, quod nollet, nisi quod anulum, quo delectabatur, in mari abiecerat. Unum est sine dolore esse, alterum cum voluptate. Laboro autem non sine causa; Theophrasti igitur, inquit, tibi liber ille placet de beata vita? Nihil opus est exemplis hoc facere longius. Duo Reges constructio interrete. Graecum enim hunc versum nostis omnes Suavis laborum est praeteritorum memoria. Haec et tu ita posuisti, et verba vestra sunt.</p>
<h2>Article secondary heading</h2>
<p>Nos commodius agimus. A mene tu? Tantum dico, magis fuisse vestrum agere Epicuri diem natalem, quam illius testamento cavere ut ageretur. Tenesne igitur, inquam, Hieronymus Rhodius quid dicat esse summum bonum, quo putet omnia referri oportere? Nihilo beatiorem esse Metellum quam Regulum. Sed quanta sit alias, nunc tantum possitne esse tanta. Philosophi autem in suis lectulis plerumque moriuntur. Esse enim, nisi eris, non potes.</p>
<p>Sunt enim quasi prima elementa naturae, quibus ubertas orationis adhiberi vix potest, nec equidem eam cogito consectari. Id Sextilius factum negabat. Quorum sine causa fieri nihil putandum est. Quae autem natura suae primae institutionis oblita est?</p>
</article>
</main>
<aside aria-label="Sidebar">
<section>
<h2>Share</h2>
<ul>
<li><a href="#">Facebook</a></li>
<li><a href="#">Twitter</a></li>
<li><a href="#">Email</a></li>
</ul>
</section>
<section>
<h2>Recommended</h2>
<ul>
<li>
<article>
<h3><a href="#">Related article</a></h3>
<p>Article description</p>
</article>
</li>
<li>
<article>
<h3><a href="#">Related article</a></h3>
<p>Article description</p>
</article>
</li>
</ul>
</section>
</aside>
<footer>
<ul>
<li><a href="#">Footer link</a></li>
<li><a href="#">Footer link</a></li>
<li><a href="#">Footer link</a></li>
<li><a href="#">Footer link</a></li>
<li><a href="#">Footer link</a></li>
</ul>
</footer>
</body>
Here is the layout in CodePen in case you want to have a play around with it (sorry mobile users, it’s not mobile friendly):
See the Pen
Mock up page layout v2 (sections article) by Daniel Tonon (@daniel-tonon)
on CodePen.
Using aria-labelledby
But let’s assume that you have a huge international audience that speaks all sorts of languages. In that case, it is better to use the aria-labelledby
attribute. Here is what that would look like:
<body>
<header>
<a href="/" title="Go to home page">
<img src="logo.png" alt="Site logo">
</a>
<nav aria-labelledby="primary-nav-label">
<div id="primary-nav-label" hidden>Primary</div>
<ul>
<li><a href="#">Primary nav</a></li>
<li><a href="#">Primary nav</a></li>
<li><a href="#">Primary nav</a></li>
<li><a href="#">Primary nav</a></li>
</ul>
</nav>
<form role="search" aria-labelledby="search-label">
<div id="search-label" hidden>Site</div>
<label>
<span>Search</span>
<input type="search"/>
</label>
<button type="submit">Submit</button>
</form>
</header>
<nav aria-labelledby="secondary-nav-label">
<div id="secondary-nav-label" hidden>Secondary</div>
<ul>
<li><a href="#">Secondary nav</a></li>
<li><a href="#">Secondary nav</a></li>
<li><a href="#">Secondary nav</a></li>
<li><a href="#">Secondary nav</a></li>
<li><a href="#">Secondary nav</a></li>
</ul>
</nav>
<main>
<article>
<h1>Main article heading</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quae sunt igitur communia vobis cum antiquis, iis sic utamur quasi concessis; Nihil acciderat ei, quod nollet, nisi quod anulum, quo delectabatur, in mari abiecerat. Unum est sine dolore esse, alterum cum voluptate. Laboro autem non sine causa; Theophrasti igitur, inquit, tibi liber ille placet de beata vita? Nihil opus est exemplis hoc facere longius. Duo Reges constructio interrete. Graecum enim hunc versum nostis omnes Suavis laborum est praeteritorum memoria. Haec et tu ita posuisti, et verba vestra sunt.</p>
<h2>Article secondary heading</h2>
<p>Nos commodius agimus. A mene tu? Tantum dico, magis fuisse vestrum agere Epicuri diem natalem, quam illius testamento cavere ut ageretur. Tenesne igitur, inquam, Hieronymus Rhodius quid dicat esse summum bonum, quo putet omnia referri oportere? Nihilo beatiorem esse Metellum quam Regulum. Sed quanta sit alias, nunc tantum possitne esse tanta. Philosophi autem in suis lectulis plerumque moriuntur. Esse enim, nisi eris, non potes.</p>
<p>Sunt enim quasi prima elementa naturae, quibus ubertas orationis adhiberi vix potest, nec equidem eam cogito consectari. Id Sextilius factum negabat. Quorum sine causa fieri nihil putandum est. Quae autem natura suae primae institutionis oblita est?</p>
</article>
</main>
<aside aria-labelledby="sidebar-label">
<div id="sidebar-label" hidden>Sidebar</div>
<section>
<h2>Share</h2>
<ul>
<li><a href="#">Facebook</a></li>
<li><a href="#">Twitter</a></li>
<li><a href="#">Email</a></li>
</ul>
</section>
<section>
<h2>Recommended</h2>
<ul>
<li>
<article>
<h3><a href="#">Related article</a></h3>
<p>Article description</p>
</article>
</li>
<li>
<article>
<h3><a href="#">Related article</a></h3>
<p>Article description</p>
</article>
</li>
</ul>
</section>
</aside>
<footer>
<ul>
<li><a href="#">Footer link</a></li>
<li><a href="#">Footer link</a></li>
<li><a href="#">Footer link</a></li>
<li><a href="#">Footer link</a></li>
<li><a href="#">Footer link</a></li>
</ul>
</footer>
</body>
Results of using aria
The heading structure for the site at this point looks like this:
Main article heading
Article secondary heading
Share
Recommended
Related article
Related article
The document outline (assuming that the original outline algorithm is implemented) looks like this:
Document
Primary
Secondary
Main article heading
Article secondary heading
Sidebar
Share
Recommended
Related article
Related article
You might be thinking that the document outline looks a bit bare. Shouldn’t things like the header and footer and search be announced in there as well? Keep in mind that this is just the explicit stuff. We get a lot of implicit information provided to the user for free by using correct HTML elements in a good structure. This is a simplified version of how a screen reader user might experience the site:
- [Text used in the
element]
- Banner landmark
- Link, site logo [(on focus) “go to home page”]
- “Primary” navigation landmark
- [List of navigation links]
- “Site” search landmark
- “Secondary” navigation landmark
- [List of navigation links]
- Main landmark
- “Main article heading” article landmark, heading level 1
- [Content]
- Heading level 2, “Article secondary heading”
- “Sidebar” complimentary landmark
- “Share” region landmark, heading level 2
- “Recommended” region landmark, heading level 2
- List with 2 items
- Item, “Related article” article landmark, heading level 3
- Item, “Related article” article landmark, heading level 3
- Content info landmark
As you can see, the site structure becomes quite clear and understandable to screen reader users when you factor in all of the extra implicit information that you get from using a good HTML structure
So, even though no browser supports the document outline algorithm, it is still worth putting some effort into thinking about the outline. Screen readers still tell users what type of section something is, where sections start and (sometimes) end (depends on the screen reader), and what the section label is. This means that your efforts to make a good document structure do not go to waste.
This type of structure comes with multiple benefits:
- The page is 100% compatible with the document outline algorithm, future proofing it in-case the algorithm is ever implemented in a real browser.
- The heading structure is completely logical.
- Screen reader users navigating via headings can quickly jump to important information.
- Screen reader users navigating via landmarks have lots of useful landmarks to move about the page.
- Screen reader users are able to quickly understand what each section contains without having to read any of the content inside of them.
- Content is grouped into semantic sections, so screen reader users do not get confused when leaving one section and entering another.
- Search engines are able to better understand what information each section holds, which could potentially improve SEO.
- Sighted users can take advantage of native browser features like Reader Mode.
What happens when you need h7?
There is one more sticking point when it comes to labeling sectioning elements that I haven’t addressed yet. Let’s say you have somehow managed to use up all six native heading levels and are now stuck needing one more. What do you do?
You could use the aria-labelledby
technique if it is just for the sake of labeling a section. Let’s say that you really want this heading to appear in the heading structure though, or maybe you just want to avoid using IDs as much as possible. Whatever the reason, you need an
element but
doesn’t exist.
This is when the aria-level
attribute comes to the rescue. The aria-level
attribute will define what the heading level should be for elements that have role="heading"
applied to them. This is how the W3C recommend creating a
element:
<div role="heading" aria-level="7">This is a valid heading level 7 element</div>
Not all screen readers support this syntax. I know that JAWS treats these like
elements rather than
elements. If you know of any screen readers that this doesn’t work in, please report the bug to the screen reader developer and also leave a comment down below.
When I need to reach for an
, I’ll often use the implied role="heading"
from an
element instead. The aria-level
attribute will override the implicit “6” level of the
element. This isn’t exactly endorsed by the W3C though. It is cleaner and will allow the heading to still appear in document outline and heading structure testing tools (though they will typically appear as
or
level headings, not as
level headings).
<h6 aria-level="7">This is also a valid heading level 7 element</h6>
By using aria-level
, you now have access to an infinite number of heading levels!
Does your site have a good structure?
Now that you know how to do a proper HTML structure, are you able to apply what you have learned to your website?
I found a pretty good browser extension called “Headings Map” that is available for both Chrome and Firefox. This extension will allow you to easily see both a flat heading structure representation of your site (i.e. how all browsers currently read the heading structure) and what the document structure looks like in a browser that supports the document outline algorithm (i.e. how a theoretical future browser that supports the outline algorithm would present the site structure). The HTML5 Outline view needs to be enabled in the settings menu first. This is to prevent users from being fooled into thinking that they are able to use the outline algorithm in production sites.
Headings Map does not currently support the aria-label
and aria-labelledby
attributes on sectioning elements in the HTML5 outline tab. I have been talking with the developer and he is working on fixing this issue. If you know of a good document outline testing tool that already takes aria-label
and aria-labelledby
into account, please share a link to it in the comments.
Once you have a good document structure testing tool, check that both the heading structure and the document outline display a logical order with no missing headings or missing section labels anywhere.
Download and use a screen reader
The best way to test the implied semantics that you get from using correct HTML is to download an actual screen reader and try navigating your site with it. NVDA is one of the most used screen readers used by real screen reader users. It’s also free!
Be aware that the default settings for NVDA are optimized for usage by blind users. These default settings can drive sighted users insane. To enjoy your time using NVDA, perform the following steps (steps are based on a Windows set up, I don’t have a Mac):
- Download NVDA and install it
- Create a shortcut to NVDA in your task bar (You will be opening and closing it regularly while testing)
- Open NVDA from the task bar
- Find NVDA in your system tray
- Right click the tray icon > “preferences” > “settings”
- Select “mouse” in the left panel
- Deselect “Enable mouse tracking” (You can now move your mouse without NVDA screaming at you)
- Press “OK”
- Right click the tray icon > “Tools” > “Speech Viewer” (You can now see a log of everything NVDA says, don’t rely purely on this when testing though)
- In the Speech Viewer, check the “Show Speech Viewer on Startup” checkbox (It will open the Speech Viewer when you open NVDA)
- Familiarize yourself with some of the keyboard controls
- To close NVDA, Right click the tray icon > “Exit” > “OK”
NVDA currently doesn’t support
and
elements. There is an issue on GitHub for supporting
elements. When I began writing this article
elements were already supported. Support for
seems to have dropped for some reason. This means NVDA should be fixed. It doesn’t mean you should stop using the correct semantics in your HTML.
Build your website with the document outline in mind then test the semantics with Headings Map and NVDA (or another screen reader). If you do, you will make your screen reader users very happy. You might even make the search engines happier too. ?
Special thanks to Eric Bailey (accessibility adviser for CSS Tricks) and Kevin Galvin (a principal consultant at me 2 accessibility) for their advice around the usability issues of using a visually hidden
element at the top of the page and suggesting aria-label
as an alternative to using visually hidden headings.
The post How to Section Your HTML appeared first on CSS-Tricks.