Correct heading structure means using one <h1> per page for the primary topic, then nesting <h2>–<h6>in order without skipping levels. Headings define a page's outline — and that outline is how screen readers, search engines, and AI systems understand and navigate your content. Get it wrong, and all three lose the plot.
<div>s.heading-order fails when levels are skipped (h1 → h3); empty-heading fails on any heading with no text content.<h1> is the second-most-important on-page ranking signal after <title> (multiple independent industry studies, 2023–2025).Think of headings as a table of contents that builds itself. If chapter 1 jumps to chapter 3, readers — human or machine — assume something is missing.
Headings serve three distinct audiences simultaneously, and a single broken hierarchy disappoints all three.
H in NVDA, VO-Cmd-H in VoiceOver, or the heading rotor in TalkBack to jump from heading to heading. Skipped levels and missing <h1> turn that navigation into guessing.<h1> tells Google the page's primary topic; <h2>s define its sub-topics. A page with no <h1>, or with five of them, sends a confused signal.The <h1> is the page's primary topic — the equivalent of the title of a chapter. HTML5 technically allows multiple <h1>s if each is inside its own <section>, but assistive-tech support is uneven and search engines still expect one. One <h1> per page is the safest default in 2026.
Headings can drop only by one level at a time. <h1> → <h2> is fine. <h1> → <h3>fails the heading-order audit and confuses screen-reader users, who hear the gap as "something is missing."
Never pick a heading level because it looks the right size. If you need big text inside a banner, use a <p> with CSS. Reserve heading tags for actual section starts.
The <section> element is meant to be a thematic grouping, and the WAI-ARIA spec recommends every section have a heading to give the resulting landmark a name. Otherwise the section becomes an unnamed region in the accessibility tree.
CSS Grid and Flexbox can reorder content visually, but the DOM order is what screen readers and search engines see. Make sure your heading order in the source code matches the order users see — not just the visual layout.
Most heading bugs fall into four patterns: skipped levels, multiple <h1>s, headings used for visual size, and empty headings. Here is what each looks like and how to fix it.
<header>
<h1>Greadme</h1> <!-- site name as h1 -->
</header>
<main>
<h1>Pricing Plans</h1> <!-- second h1 on the same page -->
<h3>Starter</h3> <!-- skips h2 -->
<p>$0/mo</p>
<h2></h2> <!-- empty heading used as a divider -->
<h2>Sale ends Friday!</h2> <!-- heading used purely for visual size -->
<p>Get 30% off through May 5.</p>
</main><header>
<a href="/" aria-label="Greadme home">
<img src="/logo.svg" alt="" /> <!-- logo, not a heading -->
</a>
</header>
<main>
<h1>Pricing Plans</h1> <!-- single, page-level h1 -->
<section aria-labelledby="starter-h">
<h2 id="starter-h">Starter</h2>
<p>$0/mo — for solo developers.</p>
<h3>What's included</h3> <!-- proper drop, h2 to h3 -->
<ul><li>5 scans/month</li></ul>
</section>
<section aria-labelledby="pro-h">
<h2 id="pro-h">Pro</h2>
<p>$29/mo — for small teams.</p>
</section>
<aside class="banner">
<p class="banner__headline">Sale ends Friday — 30% off.</p>
<!-- styled paragraph, not h2 -->
</aside>
</main>Heading audits are deterministic — automated tools catch every skipped level and empty heading reliably. The harder question is whether your <h1> actually describes the page well.
<h1>, duplicate <h1>, or skipped level. Each issue comes with an AI-generated fix or one-click GitHub PR.<h1> survived client-side rendering.Sketch h1 → h2 → h3 in plain text first. If the outline reads naturally without the body copy, the page will too. If the outline jumps around, the body will never recover.
The <h1> should tell Google and AI search engines what query the page answers. It does not have to match the <title> exactly, but it should cover the same primary topic.
The site logo is not the page's topic. Wrap it in an <a> with an aria-label instead. Reserve the <h1> for the page-specific topic that follows.
role="heading" aria-level="2" works in a pinch, but native <h2> is always preferable — better support, simpler markup, and no risk of forgetting the level when the design changes.
Decouple semantic level from visual size. A class like .text-xl can style any element, so an <h2> can look small and a paragraph can look big — without breaking the document outline.
An <h2> with no text content (used as a styled spacer or icon container) fails the empty-heading audit and confuses screen-reader heading lists. If a divider is purely decorative, use an <hr> or a styled <div> with aria-hidden="true".
A heading inside a <button> or <a> changes the accessible name of the interactive control and disrupts heading navigation. Keep them separate: heading first, then the link or button beneath it.
Chrome DevTools shows the page's heading outline in its Accessibility pane. Read it as a table of contents — if it reads like a clean outline, you are done. If it reads like nonsense, fix the source.
What's happening: The page has no primary heading — usually because designers used a styled <div> for the title.
Fix: Convert the visual title into a real <h1> and apply the existing styles via a class. This is one of the highest-impact SEO fixes for any page.
What's happening: The site uses <h1> for the logo and again for the page title, or a CMS theme allows authors to add <h1> in the body.
Fix: Demote secondary <h1>s to the appropriate level (typically <h2>), and lock the template so only one <h1> can be rendered.
What's happening: A subsection is rendered as <h4> because <h4> "looked the right size," not because it is four levels deep.
Fix: Replace the <h4> with the correct level (<h3>) and use a CSS class for the size. The audit clears immediately.
What's happening: A theme uses <h2></h2> as a styled rule with a CSS background.
Fix: Replace it with an <hr> or a decorative <div aria-hidden="true">. The empty-heading audit clears, and screen-reader heading lists become readable again.
Three different tools can make text "look like a heading." Only two of them actually create a heading in the document outline.
| Approach | Adds to Document Outline? | Recognized by Screen Readers? | Best Used For |
|---|---|---|---|
Native <h1>–<h6> | Yes | Yes | Default. Use this 99% of the time. |
role="heading" aria-level="N" | Yes (via ARIA) | Yes | Edge cases where you cannot use a native heading tag (e.g. legacy template constraints). |
Styled <div> or <p> | No | No | Visual size only — promotional banners, hero copy that is not a true section heading. |
| Empty heading + CSS background | Yes (and breaks) | Yes (announced as "blank heading") | Never. This is always an audit failure. |
HTML5 technically allows it inside separate <section> elements, but in practice screen readers and search engines still treat the page as having one primary topic. Use a single <h1> per page in 2026 — it is the safest, most-supported pattern.
Yes. Skipping levels (<h1> → <h3>) fails WCAG 1.3.1 in the heading-order audit and confuses screen-reader users navigating by heading. It also weakens the topical signal Google extracts from the page.
The heading-order audit fails when levels are skipped (going from h1 directly to h3, for example). The empty-heading audit fails when any heading tag has no text content. They are separate audits — a page can fail one without the other.
Yes — that is the recommendation in the WAI-ARIA Authoring Practices. The <section> element creates a region landmark, and a heading inside it gives the region an accessible name. Without one, the section is exposed as an unnamed region.
Both. Google has confirmed that headings are a direct on-page topical signal, with <h1> carrying the most weight after <title>. They also affect SEO indirectly through the accessibility wins that improve dwell time and engagement.
They use the heading tree as a page outline for retrieval and citation. When generating an answer, they often cite the section under a specific <h2> or <h3> — so a clean, descriptive heading hierarchy directly improves your odds of being cited and your visibility in AI Overviews.
Override the template so the site logo is wrapped in an <a> with aria-label instead of an <h1>, and audit any blocks (hero, banner, post title) that emit their own <h1>. Reserve <h1> for the page's single primary topic and demote the others to <h2>.
Heading structure is the most underrated lever in accessibility, SEO, and AI visibility. One <h1> per page, no skipped levels, no headings used for visual size, no empty tags — that is the entire rulebook. Get it right and screen-reader users navigate cleanly, Google understands your topic, and AI search engines cite you accurately.
Run a Greadme deep scanto see your page's full heading outline, catch every heading-order and empty-heading violation, and ship the fixes in a one-click GitHub PR.