WCAG 2.4.6: Headings and Labels
Screen reader users skim a page the way sighted users do — by jumping between headings and reading the labels on controls. This criterion asks one simple thing: the headings and labels you use must describe their topic or purpose. A heading called “More” or a field labelled “Input” tells nobody anything. Specific, meaningful text is what makes a page navigable.
The success criterion, in full
Headings and labels describe topic or purpose.
That single sentence is the entire normative requirement. Note what it does not say: it does not require you to add headings or labels where none exist. It governs only the headings and labels that are present — those must be descriptive.
Why headings and labels matter
A sighted user scanning a long page never reads it top to bottom. Their eye jumps to the bold section titles, finds the part they need, and dives in. Screen reader users do exactly the same thing — but they do it with a keyboard shortcut. Pressing H in most screen readers jumps to the next heading; opening the rotor or elements list shows every heading on the page at once. This only works if the headings actually say what each section is about.
The same is true of labels. When a user tabs into a form field, the screen reader announces its label. “Email address, edit text” tells them exactly what to type. “Edit text” with no useful label — or a label like “Field 3” — leaves them guessing, and the cost of guessing wrong on a checkout or a job application is high.
This benefits everyone, not just screen reader users. Clear headings help people with cognitive disabilities build a mental model of the page, help people with low vision who zoom in and lose the surrounding context, and — as a bonus — give search engines the structural signals they use to understand and rank your content. Descriptive headings and labels are simply good writing.
What counts as a “label”
This trips people up, because WCAG uses label more broadly than the HTML <label> element. In WCAG, a label is any text or component that identifies a control for the user. So 2.4.6 reaches further than just form fields:
Section headings
Every h1–h6 on the page. The title of a section must describe what that section contains.
Form field labels
The visible label associated with an input, select, textarea, checkbox, or radio group.
Button and link text
The accessible name of a button or a link that acts as a control — 'Download report', not 'Click here'.
Widget names
The names of tabs, accordions, dialogs, and other ARIA widgets that identify their purpose to the user.
What 2.4.6 does not cover is ordinary body text. A paragraph in the middle of an article is neither a heading nor a label, so this criterion says nothing about it. The scope is specifically text that acts as a heading or that names a control.
Descriptive, not present
The single most important thing to understand about 2.4.6 is that it is a quality requirement, not a presence requirement. It does not say “you must have headings” or “every field needs a label.” It says that if you have headings and labels, they must be descriptive.
The requirement that a label must actually exist and be wired up in code comes from two other criteria you should satisfy together with this one:
- 1.3.1 Info and Relationships (A) — headings must be marked up as real headings, and labels must be programmatically associated with their controls.
- 3.3.2 Labels or Instructions (A) — form controls that need a label to be understood must have one.
Think of it as a pipeline: 1.3.1 and 3.3.2 make sure the heading or label exists and is exposed correctly; 2.4.6 makes sure the words themselves are worth reading. Passing 2.4.6 while failing 1.3.1 (for example, a “heading” that is only bold text, not an actual <h2>) still leaves the page inaccessible — so aim to satisfy all three.
Code examples
Vague vs. descriptive headings
A heading pulled out of context, in a screen reader’s headings list, has to stand on its own. “Overview” and “Details” repeated three times down a page describe nothing.
<!-- ✗ Vague: identical, non-descriptive headings -->
<h2>Overview</h2>
<h2>Overview</h2>
<h2>More</h2>
<!-- ✓ Descriptive: each heading names its section -->
<h2>Pricing overview</h2>
<h2>Team plan features</h2>
<h2>Frequently asked questions</h2>Real, descriptive form labels
Associate a persistent <label> with each control using for/id, and make the text say exactly what belongs in the field.
<!-- ✗ Non-descriptive, and placeholder used as the label -->
<input type="text" placeholder="Enter value" />
<label for="f2">Field</label>
<input id="f2" type="text" />
<!-- ✓ Descriptive labels, persistent and associated -->
<label for="work-email">Work email address</label>
<input id="work-email" type="email" autocomplete="email" />
<label for="card-number">Card number</label>
<input id="card-number" inputmode="numeric" autocomplete="cc-number" />Distinguish repeated link and button labels
Several “Read more” links in a row all read the same in a links list. Extend the accessible name so each describes its own destination — a visible extension is best, but a visually-hidden span or a matching aria-label works too.
<!-- ✗ Ambiguous: three identical link names -->
<a href="/pricing">Read more</a>
<a href="/security">Read more</a>
<!-- ✓ Each label describes its own purpose -->
<a href="/pricing">Read more<span class="sr-only"> about pricing</span></a>
<a href="/security">Read more<span class="sr-only"> about security</span></a>
<!-- ✓ Or an explicit, descriptive button label -->
<button type="submit">Place order & pay $49</button>Common mistakes
- Generic headings like 'Overview', 'Introduction', 'Section 1', or 'More' that do not say what the section is actually about.
- Placeholder text used in place of a real label — it vanishes on typing, is low contrast, and is not a reliable accessible name.
- Form labels that describe the format instead of the purpose, e.g. 'MM/DD/YYYY' as the only label instead of 'Date of birth'.
- Repeated 'Read more', 'Click here', 'Learn more', or 'Details' links whose labels are indistinguishable out of context.
- Vague button names such as 'Submit', 'OK', or 'Go' where a specific action — 'Create account', 'Apply filters' — would be clearer.
- Icon-only buttons with no accessible name at all (e.g. a bare magnifying-glass button with no 'Search' label).
- Headings written for style, not meaning — a marketing tagline as an h2 that reads well visually but describes nothing when isolated.
- Using bold or large text that looks like a heading but is not marked up as one, so it fails 1.3.1 and provides no navigable heading.
How to test for 2.4.6
- 1
List every heading and read it in isolation
Use a screen reader's headings list (VoiceOver rotor, NVDA/JAWS elements list) or a browser extension that outlines the heading structure. Read each heading on its own — with no surrounding content — and ask whether it describes the section that follows. If it could belong to any section, it is not descriptive enough.
- 2
Tab through every form control
Move through each field with the Tab key and listen to what the screen reader announces. The announced name should tell you exactly what to enter. 'Edit text' with no useful label, or a name like 'Field', is a failure.
- 3
Pull up the links and buttons list
Open the screen reader's list of links (and of form controls). Scan for duplicates like several 'Read more' entries, and for generic names like 'Click here' or 'Submit' that don't say what happens. Each should describe its own purpose.
- 4
Check for descriptive intent, not just presence
Automated tools can flag a missing label or an empty heading, but they cannot judge whether the words are meaningful — a heading called 'Stuff' passes an automated check and fails 2.4.6. This is fundamentally a manual, human-judgment review.
- 5
Verify against the page title and purpose
Confirm the top-level heading and section headings match what the page and its sections are really about. Cross-check with 2.4.2 Page Titled so the page title, h1, and section headings tell one consistent story.
Because 2.4.6 is a judgment call about wording, it is one of the criteria automated scanners consistently miss. Use the Heading Analyzer to surface every heading at once for review, then work through the full WCAG 2.2 checklist.
Related success criteria
1.3.1 Info and Relationships — A
The structural counterpart. 1.3.1 requires headings to be real headings and labels to be programmatically associated in code; 2.4.6 requires the text of those headings and labels to be descriptive.
3.3.2 Labels or Instructions — A
Requires form controls to actually have a label. Together with 2.4.6: 3.3.2 says the label must exist, 2.4.6 says it must clearly describe the field’s purpose.
2.4.4 Link Purpose (In Context) — A
Focuses specifically on links being understandable. Vague 'Read more' link text is the overlap where 2.4.4 and 2.4.6 both apply.
4.1.2 Name, Role, Value — A
Ensures every control exposes an accessible name to assistive tech. 2.4.6 then requires that name to be descriptive rather than generic.
Browse every criterion in the WCAG Success Criteria hub or audit your heading outline with the Heading Analyzer.
Frequently asked questions
What does WCAG 2.4.6 Headings and Labels require?
It requires that any headings and labels present on a page describe their topic or purpose. The full normative text is just one sentence: 'Headings and labels describe topic or purpose.' It does not force you to add headings or labels where none exist — that is covered by other criteria — but wherever you do use a heading or a label, it must be meaningful and specific enough that a user can understand what the section contains or what a control does. It is a Level AA success criterion introduced in WCAG 2.0 and carried into WCAG 2.1 and 2.2.
Does 2.4.6 require every page and form field to have a heading or label?
No — that is the most common misreading. 2.4.6 is a quality bar, not a presence requirement. It only applies to the headings and labels you already have, and asks that they be descriptive. The requirement to actually provide a label for a form control comes from 3.3.2 Labels or Instructions (Level A) and 1.3.1 Info and Relationships. So the two work together: 3.3.2 and 1.3.1 say a label must exist and be programmatically associated, and 2.4.6 says that label must clearly describe the field's purpose.
What counts as a 'label' in WCAG 2.4.6?
WCAG uses 'label' more broadly than the HTML <label> element. A label is any text or component presented to users to identify a component within the web content — form field labels, but also button text, link text used as a control name, tab labels, and the accessible names of interactive widgets. So 2.4.6 covers the visible text of a 'Submit order' button and the label on an email field alike. It does not, however, cover every piece of body text — only text that acts as a heading or as a label for a control.
Do headings and labels have to be unique to pass 2.4.6?
Uniqueness is not strictly required, but it helps. The criterion only asks that headings and labels be descriptive, not that no two are ever the same. That said, when several headings or labels sit near each other and read identically — three 'Read more' links, or two 'Name' fields with no further distinction — they stop describing their individual purpose. The practical fix is to make each one specific: 'Read more about pricing', 'First name', 'Company name'. Descriptive usually ends up being unique where it needs to be.
How is 2.4.6 different from 1.3.1, 2.4.10, and 2.4.4?
They form a cluster around structure and naming. 1.3.1 Info and Relationships (A) is about marking headings up as real headings and associating labels programmatically — the structure must exist in code. 2.4.10 Section Headings (AAA) goes further and expects headings to actually organize the content into sections. 2.4.4 Link Purpose (In Context) (A) is specifically about links being understandable from their text plus context. 2.4.6 sits across all of them at AA: whatever headings and labels you have, in code and on screen, must clearly describe topic or purpose.
Is placeholder text a valid label under 2.4.6?
No. Placeholder text disappears as soon as the user starts typing, is often too low-contrast to read, and is not reliably exposed as the field's accessible name — so it fails both 3.3.2 (a persistent label must exist) and, in spirit, 2.4.6 (the label the user relies on is gone when they need it). Always provide a real, persistent <label> that describes the field's purpose, and treat placeholder text only as an optional formatting hint, never as the label itself.