2.4.10 Section Headings
WCAG 2.2 · 2.4.10 AAA Operable
What it requires
Where written content is organised into sections, those sections must be introduced by
headings. The criterion is about presence, not styling: if a block of content is
conceptually a distinct section, it needs a real heading to mark its start. It applies only
when the content actually divides into sections — it does not force you to invent artificial
divisions, and it does not dictate a specific heading level or wording. In HTML the headings
should be true heading elements (<h2>–<h6>), so the
section structure is exposed programmatically and not just visually.
Strong section headings help everyone, but they are essential for some users:
- Screen-reader users navigate by heading (jumping H-to-H or opening a headings list); missing or fake headings leave them reading linearly with no map.
- People with cognitive and learning disabilities rely on headings to chunk long content, preview structure, and find where they left off.
- Low-vision and magnifier users, who see only a small slice of the page, use headings as orientation landmarks.
How to detect it
| Check | What to look for |
|---|---|
| Manual review | Read the page and identify its sections. Does each distinct section begin with a heading? Watch for "headings" that are really bold or large text. |
| Screen reader | Pull up the headings list (e.g. NVDA/JAWS) or rotor (VoiceOver). Every section should appear; the outline should match the visible structure. |
| Keyboard / structure | Navigate by heading shortcut. If a visually obvious section is skipped, it lacks a real heading. |
| Zoom | At 200–400% zoom, confirm the content still reads as headed sections rather than one undifferentiated wall of text. |
| Automated tools | Largely a human judgement. axe and similar tools flag empty or skipped-level headings, but cannot tell whether a section that should have a heading is missing one. |
How to fix it
- Identify the page's logical sections from the content itself.
- Give each section a real heading element, not styled text.
- Make the heading text describe the section's topic concisely.
- Keep levels nested logically (no skipping from
h2toh4). - Pair each heading with its content using
<section>where it clarifies the grouping.
<section>
<h2>Shipping & returns</h2>
<p>Orders ship within two business days...</p>
</section>
<section>
<h2>Warranty</h2>
<p>Every product is covered for 12 months...</p>
</section>
Copy-paste tests
Automated coverage
There is no fully automated axe-core rule for 2.4.10 — a tool cannot know which content blocks are conceptually distinct sections that require a heading. This criterion needs manual review, using the console check and steps below to surface candidates.
Run this in the browser console
// Read-only: lists landmark/section containers and the headings they hold.
const suspects = [...document.querySelectorAll('section, article, aside, [role="region"]')]
.map(el => {
const h = el.querySelector(':scope > h1, :scope > h2, :scope > h3, :scope > h4, :scope > h5, :scope > h6');
if (!h) el.style.outline = '2px dashed orange'; // visual hint only
return { el, heading: h ? h.textContent.trim() : '(none)', hasHeading: !!h };
});
console.table(suspects.map(({ heading, hasHeading }) => ({ heading, hasHeading })));
console.log('Containers without a direct heading:', suspects.filter(s => !s.hasHeading).map(s => s.el));
What to check manually: for every visually distinct section, confirm a real heading element (not bold/large styled text) introduces it, and that the heading wording actually describes that section's topic — neither is something a script can confirm.
Related
- WCAG 2.2 criteria index
- Learn catalog
- Lesson: Structure & semantics — headings, landmarks, and relationships.