Headings must include discernible text
Last updated:
Related Guides
Headings must not be empty and must have discernible text
Every heading element must expose readable text to assistive technologies. Empty or hidden headings create “blank” announcements and break the page outline. This affects screen reader users and anyone who navigates by headings on desktop and mobile.
Why It Matters
People who use screen readers jump through content by heading level. An empty or hidden heading is announced as blank, which is confusing and wastes time.
Clear, descriptive headings reduce cognitive load and help users understand section purpose. Consistent structure benefits speech recognition users who issue voice commands like “go to next heading.”
Search engines also interpret heading structure, so meaningful text improves document semantics.
Common Causes
- Using empty h1–h6 tags as spacers or layout hooks.
- Hiding heading text with
aria-hidden="true"or CSS like display:none or visibility:hidden. - Rendering heading text only via background images or CSS ::before/::after content.
- Icon-only headings with no accessible text alternative.
- JavaScript inserting heading elements without
textContentor accessible name. role="heading"used without a validaria-levelor without a name.
How to Fix
- Use semantic h1–h6 for section titles. Provide real text nodes inside the heading.
- Do not apply
aria-hidden="true"to any heading or its text. Remove it if present. - Do not hide the only heading text with display:none or visibility:hidden. If text must be visually hidden while remaining accessible, use a “visually hidden” utility that keeps it available to assistive tech.
- Do not rely on CSS-generated content or background images for critical heading text. Put the words in the DOM.
- Replace empty spacer headings with proper CSS spacing (margins, padding) and remove the empty tags.
- If you must use
role="heading"(e.g., in a widget), includearia-level="1–6"and an accessible name via text,aria-label, oraria-labelledby. - Make headings descriptive of their section purpose (WCAG 2.2: 1.3.1 Info and Relationships, 2.4.6 Headings and Labels, 4.1.2 Name, Role, Value).
Recommendation: Favor visible text in headings whenever possible; reserve visually hidden text for rare icon-only designs.
How to Test
- Visual/DOM check:
- Inspect each h1–h6. Confirm there is
textContentor an accessible name. - Ensure no
aria-hiddenon the heading or on its only text node. - Verify text is not removed with display:none or visibility:hidden.
- Confirm text is not solely from ::before/::after or background images.
- Keyboard check (informational):
- Tabbing should not land on headings (they are not interactive). If a heading receives focus, review why and remove
tabindexunless necessary for a composite widget.
- Screen reader check (desktop):
- NVDA/JAWS: Press H to move by headings and use the headings list (NVDA: Insert+F7 > Headings; JAWS: Insert+F6). No item should be blank; each entry should read meaningful text and level.
- VoiceOver (macOS): VO+U to open the Rotor, choose Headings. Ensure each heading has text and correct order.
- Mobile/touch check:
- iOS VoiceOver: Use the Rotor set to Headings and swipe up/down to navigate. Confirm there are no empty announcements.
- Android TalkBack: Use the reading controls for Headings and navigate. Ensure all headings are announced with text.
- Automated check:
- Run an a11y scanner that flags “headings must have discernible text.” Manually confirm any flagged items.
Good Example
<h2 class="section-title">
<span class="icon-bell" aria-hidden="true"></span>
Notifications
</h2>
<!-- Icon-only visual design with accessible, visually hidden text -->
<h3 class="section-title">
<span class="icon-stats" aria-hidden="true"></span>
<span class="sr-only">Sales Dashboard</span>
</h3>
<style>
.sr-only {
position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
</style>Bad Example
<h2></h2> <!-- empty -->
<h3 aria-hidden="true">Support</h3> <!-- hidden from AT -->
<h4><span class="icon-help" aria-hidden="true"></span></h4> <!-- icon-only, no text -->Quick Checklist
- Every h1–h6 contains real, readable text in the DOM.
- No heading or its only text node is
aria-hidden. - Heading text is not removed with display:none or visibility:hidden.
- Do not rely on CSS-generated content or images for heading words.
- Icon-only headings include an accessible text alternative.
role="heading"(if used) includesaria-leveland an accessible name.- Headings describe the topic or purpose of their section.
- Remove empty headings; use CSS for spacing instead.