Headings are load-bearing structure for machine readers. Retrieval systems slice pages on heading boundaries, embed each slice, then return those slices as the candidate snippets an AI assistant cites. Wrong nesting puts your best paragraph in the same chunk as your footer. Five bugs we flag most often on isitready.dev scans, plus one bonus.
Multiple H1s on a single page
The <h1> confusion comes from the HTML5 outline algorithm, a 2010-era
proposal that let each <section> reset the heading scope. It was never
shipped. The W3C Markup Validator was updated on June 16, 2016 to warn
against it. The Chromium tracker closed the implementation bug as WONTFIX
in July 2021. MDN now states the rule plainly: "Prefer using only one H1
per page and nest headings without skipping levels."
So one H1. That H1 should describe the page, not the site. Wrapping your
logo in <h1> ships the same H1 text on every page, a pattern The A11Y
Project calls out because screen reader users hear identical heading
announcements across the whole site.
<!-- bad: site name as H1, article title demoted -->
<h1>Acme Corp</h1>
<h2>How we handle webhook retries</h2>
<!-- good: page-specific H1, brand goes in <header> or alt text -->
<header><img src="/logo.svg" alt="Acme Corp"></header>
<h1>How we handle webhook retries</h1>For AI parsing, the H1 is the document title in most chunking pipelines and gets attached as metadata on every child chunk. A wrong H1 mislabels every chunk derived from the page.
Skipping levels
Skipping from <h1> straight to <h3> is a WCAG 2.2 SC 1.3.1 Info and
Relationships failure (Level A). Screen readers expose headings as a
nested tree. NVDA users press H to walk forward through headings, JAWS
uses H, VoiceOver uses Control+Option+Command+H. Skipping a level
inserts a phantom parent in that tree and breaks the user's mental model
of section depth.
The same nested tree is what RAG pipelines reconstruct. Hierarchical chunking, the dominant strategy for structured documents, relies on parent-child relationships to assign each chunk its breadcrumb context. Skip from H1 to H3 and the H3 chunk gets attributed to the H1 directly, losing the missing H2's topical scope.
<!-- bad: H1 jumps to H3, no H2 anchor -->
<h1>API authentication</h1>
<h3>Rotating an API key</h3>
<!-- good: H2 establishes the section, H3 nests under it -->
<h1>API authentication</h1>
<h2>Key management</h2>
<h3>Rotating an API key</h3>If your design only needs two visual levels, use H1 and H2. Don't skip H2 because the H3 looks better in your CSS.
Headings used for visual styling
This one is everywhere. A designer wants a big bold pull-quote, the
nearest reusable component is <h2>, and now your "Trusted by 10,000
teams" slogan is structurally a top-level section heading with no
content below it. WCAG documents this exact failure as F2.
The fix is the inverse problem most teams have: they style divs as
headings (also F2). Either way, semantics and presentation got tangled.
Use a heading element when the text is the title of a content section.
Use a <p> with appropriate styles when the text is decoration.
<!-- bad: H2 used because the design wants 32px bold -->
<h2>Trusted by 10,000 teams</h2>
<div class="logo-grid">...</div>
<h2>Built for engineers</h2>
<p>Real subhead, but now it's H2 #3 on the page</p>
<!-- good: real heading for the section, styled <p> for the slogan -->
<p class="display-text">Trusted by 10,000 teams</p>
<div class="logo-grid">...</div>
<h2>Built for engineers</h2>When chunking pipelines hit a decorative H2, they open a new chunk and pull in whatever follows until the next heading. Your slogan bonds to your engineering pitch in one retrievable unit. The embedding becomes a muddled average of two unrelated topics.
Empty headings
An <h2> containing only an icon, a decorative SVG, or whitespace is a
broken navigation landmark. Screen readers announce "heading level 2"
followed by nothing. WAVE and axe-core both flag empty headings as
errors. The element is structurally promising a section that doesn't
exist.
For chunking, an empty heading tells the parser to start a new chunk with no name and no scope. The chunk inherits the previous heading's metadata or, worse, gets indexed with an empty title field that some retrievers down-rank automatically.
<!-- bad: H2 wrapping only an icon -->
<h2><svg aria-hidden="true">...</svg></h2>
<p>Encrypted at rest using AES-256...</p>
<!-- good: real text for the heading, icon as accompaniment -->
<h2>
<svg aria-hidden="true">...</svg>
Encryption at rest
</h2>
<p>Encrypted at rest using AES-256...</p>If the icon really is the section identifier, give the SVG a non-empty
aria-label matching the heading's intent. Better: write the text out
and decorate it.
H6 used for nav menus or fine print
<h6> exists for the deepest legitimate subsection in a long document.
It is not a "small text" tag. We see it abused for footer link groups,
"Quick links" sidebars, breadcrumb labels above navigation, legal fine
print. Each abuse adds a phantom heading to the document outline.
Screen reader users navigating by heading will jump to your cookie notice expecting a section. Your retrieval pipeline will create a chunk labeled "Privacy" containing the cookie banner microcopy and rank it against actual privacy documentation queries. Both outcomes are bad.
<!-- bad: H6 for a footer link cluster -->
<footer>
<h6>Company</h6>
<ul>
<li><a href="/about">About</a></li>
<li><a href="/careers">Careers</a></li>
</ul>
</footer>
<!-- good: <nav> with aria-label, no heading -->
<footer>
<nav aria-label="Company">
<ul>
<li><a href="/about">About</a></li>
<li><a href="/careers">Careers</a></li>
</ul>
</nav>
</footer>The <nav> landmark with aria-label gives assistive tech the structure
it needs without polluting your heading outline. If you need a visible
label above the link list, use a <p> styled as a label and reference
it with aria-labelledby.
Deeply nested H4-H5-H6 chains nobody reads
Six-level nesting is rare in good content. Reference manuals justify it.
Marketing pages almost never do. Sites we audit with H5 and H6 in the
wild usually got there via a CMS migration that wrapped everything in
extra <section> elements and demoted the originals.
Deep chains bloat the chunking tree without adding retrievable substance. Each extra level produces smaller chunks with thinner context. Production RAG pipelines commonly target chunk sizes between 200 and 500 tokens. H6 sections are usually one paragraph, well under that floor, so they get merged with siblings or padded with surrounding noise.
If you genuinely need a heading-styled label at level 7+, don't reach for
<div role="heading" aria-level="7">. JAWS has a documented bug where
it ignores aria-level on real heading elements. Use <h6 aria-level="7">
instead. It degrades to H6 on JAWS and works correctly elsewhere.
Honestly: rewrite the content so it doesn't need level 7.
A note on Google's actual stance
John Mueller has said publicly that fixing heading order on an existing site won't move rankings: "fixing this isn't going to change your site's rankings." He's also called headings a strong signal for understanding what a page is about. Both are true. SEO rank and AI chunkability are different problems. Heading hygiene barely moves classical search position, but it directly decides which paragraphs an LLM retrieves when answering a question that cites you.
Verify before shipping
Run isitready.dev on your canonical origin to flag every page with multiple H1s, skipped levels, empty headings, and H6 abuse. The report lists the exact heading outline per page, so you can see what a chunking pipeline sees before an AI assistant does.