Screen reader users navigate by heading rotor; generic heading text like "Section 1" or "More info" strips that rotor of its usefulness
2.4.6 Headings and Labels
In Plain Language
2.4.6 Headings and Labels (Level AA) requires that where headings (<h1>-<h6>, or elements with role="heading") and form labels (<label>, or the accessible name of a form control) are present, their text must describe the topic or purpose of the content they head or the input they label[1].
2.4.6 is a quality criterion, not an existence criterion. Whether a heading or label is marked up correctly belongs to 1.3.1 Info and Relationships[2]. Whether a form field is required to have a label at all belongs to 3.3.2 Labels or Instructions. 2.4.6 sits on top of both: given that headings and labels exist and are programmatically associated, the text itself has to be meaningful.
Why It Matters
- Screen reader users navigate by heading rotor -- NVDA exposes the page's heading list via Insert+F7, VoiceOver via VO+U, JAWS via Insert+F6. The rotor pulls heading text into a flat list stripped of visual context. "Section 1 / More info / Details / Learn more" tells that user nothing about where to jump; "Shipping options / Return policy / International orders" lets them land directly on the section they want.
- Form fields are announced to screen reader users as their accessible name plus their role: "Field 1, edit" carries no information about what to type. "Email address, edit" does. The label is often the only signal a non-sighted user has about what the input expects, because the surrounding visual layout, placeholder colour, and helper-icon tooltips are not part of the accessibility tree by default.
- Users with cognitive and learning disabilities use headings as landmarks for orientation and short-term memory offload. Generic heading text ("Section 2", "Things to know") forces the reader to hold the preceding context in working memory to make sense of what follows, which is the load the heading was supposed to lift.
- Sighted keyboard and mouse users also scan by heading. A heading outline that reads like a usable table of contents is a side effect of writing descriptive headings, not a separate feature.
Examples
Shipping Options
Choose a delivery method for your order.
Return Policy
Items can be returned within 30 days.
✔ Each heading describes the topic of its section
<h2>Shipping Options</h2>
<p>Choose a delivery method for your order.</p>
<h3>Return Policy</h3>
<p>Items can be returned within 30 days.</p>
Section 1
Choose a delivery method for your order.
More Info
Items can be returned within 30 days.
✘ Headings like "Section 1" and "More Info" do not describe the topic
<!-- FAILS: headings do not describe topic -->
<h2>Section 1</h2>
<p>Choose a delivery method for your order.</p>
<h3>More Info</h3>
<p>Items can be returned within 30 days.</p>
✔ Labels clearly describe what each field expects
<label for="email">Email address</label>
<input type="email" id="email">
<label for="phone">Phone number</label>
<input type="tel" id="phone">
✘ "Field 1" and "Field 2" do not describe the purpose of these inputs
How to Fix It
- Extract the heading list and read it in isolation. Open the rotor (NVDA Insert+F7, VoiceOver VO+U, JAWS Insert+F6) or scrape the DOM for every
<h1>-<h6>androle="heading"element. If the resulting list does not read like a table of contents a new reader could use to infer page structure, the headings are failing 2.4.6. - Rewrite each heading to name its section's topic. Replace ordinal or filler text ("Section 1", "Part 2", "Details", "More info", "Things to know") with a noun phrase that summarises the content beneath it. "Quarterly revenue by region" over "Section 3". A single word can be enough if it is specific -- 2.4.6 does not require long headings, only descriptive ones.
- Name form fields by what they collect, not where they sit. The accessible name of an input should be the data it expects: "Email address", "Shipping ZIP code", "Card verification value (3 digits)". Avoid positional labels ("Field 1", "Input"), avoid generic verbs ("Enter"), and avoid relying on a placeholder as the only label -- placeholders disappear on focus and are not reliably exposed as the accessible name.
- Put constraint and format hints into a description, not the label. When a field needs format guidance ("MM/YYYY", "minimum 8 characters"), put the hint in a separate element and connect it with
aria-describedby. The label stays short and topic-describing; the description carries the constraint. This keeps the heading rotor and the form-field list readable while still exposing the constraint to assistive tech. - Do not use heading elements for visual styling. A
<h3>chosen because it looks the right size injects a fake section into the heading outline and degrades rotor navigation. Use CSS to style a<p>or<div>, and reserve heading elements for actual document structure. This is strictly a 1.3.1 failure, but it is the most common way a page ends up with headings that cannot describe anything because they do not correspond to sections. - Test by audit, not by appearance. Pull the heading list and the form-field accessible-name list with a screen reader or an accessibility inspector (Chrome DevTools Accessibility pane, Firefox Accessibility Inspector). Read each list as a flat sequence. Every entry should stand alone.
References
- [1] W3C (2023). Understanding Success Criterion 2.4.6: Headings and Labels. W3C, Accessed 2026-04-07. https://www.w3.org/WAI/WCAG22/Understanding/headings-and-labels.html ↩
- [2] W3C (2023). Understanding Success Criterion 1.3.1: Info and Relationships. W3C, Accessed 2026-04-07. https://www.w3.org/WAI/WCAG22/Understanding/info-and-relationships.html ↩