lintpageincident.log
checksenvironmentstoolsblogfaq
sign inget started
~/blog/heading-structure-mistakes
SEOAccessibilityHeadings

Heading Structure Mistakes That Confuse Google and Screen Readers

Marius Orzaru·March 3, 2026·9 min read·updated August 29, 2026

The outline that search engines and screen readers depend on

HTML heading tags (<h1> through <h6>) create the outline of your page. They tell search engines what your content is about and how it's organized. They also tell screen readers how to navigate your page - visually impaired users jump between headings to find the content they need.

When the heading structure is wrong, both audiences suffer. Google gets confused about your page's topic. Screen reader users can't navigate. And you lose both rankings and accessibility compliance. Here are the most common mistakes.

How headings actually affect SEO

Headings are not a direct ranking factor the way a title tag is. What they do is shape how Google interprets the page, and that shows up in rankings indirectly through three mechanisms:

  • Topic clarity. Your H1 is the strongest on-page statement of what the page is about after the title tag. A vague, missing, or duplicated H1 forces Google to infer the topic from body copy, which it does less confidently.
  • Passage and snippet selection. Google pulls featured snippets and jump-to-section links from heading blocks. A page with descriptive H2s is eligible for those placements; a wall of text is not.
  • Query coverage. Each descriptive heading is a chance to match a related query. A page with one heading matches one phrasing. A page with eight well-written headings matches many.

None of that works if the hierarchy is broken. The five mistakes below are the ones that break it most often.

1. Multiple H1 tags (or no H1 at all)

The H1 tag is the main heading of your page - the primary topic signal for search engines. Every page should have exactly one.

<!-- Bad: two competing H1 tags -->
<h1>Welcome to Our Site</h1>
<h1>Best Pricing Plans</h1>

<!-- Good: one clear H1 -->
<h1>Pricing Plans</h1>
<h2>Starter Plan</h2>
<h2>Pro Plan</h2>

Having multiple H1 tags dilutes the topic signal. Having no H1 at all means Google has to guess what your page is about. Both hurt your ability to rank for your target keyword.

A common cause: component libraries or CMS templates that inject extra H1 tags. Your page might have an H1 you don't know about hidden inside a header component or widget. An h1 checker catches these in one pass, including the tags injected at runtime that never show up when you search your source files.

2. Skipped heading levels

Heading levels should follow a sequential order: H1, then H2, then H3. Jumping from H1 to H3 (skipping H2) breaks the document outline:

<!-- Bad: H1 jumps to H3 -->
<h1>SEO Guide</h1>
<h3>Meta Tags</h3>
<h3>Robots.txt</h3>

<!-- Good: proper hierarchy -->
<h1>SEO Guide</h1>
<h2>On-Page Factors</h2>
<h3>Meta Tags</h3>
<h3>Robots.txt</h3>

This matters for screen readers: users navigate by heading level, and skipped levels suggest missing content. It also matters for SEO: a logical outline helps Google understand the relationship between sections.

The usual cause? Using heading tags for styling. Developers pick H3 because it looks the right size, not because it's the right level. Use CSS for sizing and keep the heading hierarchy semantic.

3. Using headings for styling instead of structure

This is the root cause of most heading problems. Headings exist to define document structure, not to make text big and bold:

<!-- Bad: heading used for visual effect -->
<h4>Subscribe to our newsletter</h4>

<!-- Good: use a styled paragraph or span -->
<p class="text-lg font-bold">Subscribe to our newsletter</p>

If you need big bold text that isn't a content section heading, use a styled <p>, <span>, or <div>. Reserve heading tags for actual content sections.

4. Empty headings

Headings with no text content are invisible to users but visible to crawlers and screen readers. They create noise in the document outline and confuse assistive technology:

<!-- Bad: empty heading (sometimes from CMS templates) -->
<h2></h2>
<h2></h2>

<!-- Also bad: heading with only an image and no alt text -->
<h2><img src="icon.png" /></h2>

Empty headings usually come from CMS templates or dynamic components where content wasn't filled in. Audit your pages for these - they're invisible when browsing but show up immediately in a heading structure check.

5. Too many headings (or too few)

A page with 50 H2 tags is just as problematic as a page with none. Over-heading dilutes the structural signal and makes the page harder to navigate.

Too many headings: Usually happens when every small element gets a heading tag. Sidebar widgets, footer sections, and card titles don't always need to be headings.

Too few headings: Long-form content with no headings is a wall of text. Break it into scannable sections with descriptive H2 and H3 tags.

A good rule of thumb: use one H2 for each major section and H3 for subsections within those. Your heading structure should read like a table of contents.

The sectioning myth: <section> does not reset heading levels

There is a persistent belief that wrapping content in <section> or <article> creates a nested outline, so an <h1> inside a <section> is "really" an h2. This came from the HTML5 outline algorithm, which was specified but never implemented by a single browser or assistive technology, and has since been removed from the spec.

<!-- Bad: relies on an algorithm that does not exist -->
<h1>Product</h1>
<section>
  <h1>Pricing</h1>
  <section>
    <h1>Enterprise</h1>
  </section>
</section>

<!-- Good: explicit levels, which is what everything actually reads -->
<h1>Product</h1>
<section>
  <h2>Pricing</h2>
  <section>
    <h3>Enterprise</h3>
  </section>
</section>

Screen readers and search engines read the literal tag number. Nesting changes nothing. Always set the level explicitly.

Why component frameworks break this so often

Every mistake above is easy to avoid in a single hand-written HTML file. They happen because heading levels are a document-level concern and components are written in isolation.

A <Card> component that hardcodes <h3> for its title is correct on a page where cards sit under an h2, and wrong on a page where they sit directly under the h1. Neither the component nor the page knows about the other.

Three patterns that reliably cause this:

  • Shared layout headings. A header, hero, or CTA component that renders an <h1> will collide with the page's own <h1> on every route that uses both. This is the single most common source of duplicate h1 tags, and it never shows up when you review the page component alone.
  • Marketing sections dropped into arbitrary pages. Testimonial blocks, feature grids, and footers commonly ship with fixed heading levels chosen to look right in the design mock rather than to fit an outline.
  • CMS and MDX content. An author writes ## for their first heading, but the template already emits the post title as <h1> - or worse, it doesn't, and the page has no h1 at all.

The fix is to make the level a prop with a sensible default, so the page can place the component correctly:

type Props = { title: string; as?: 'h2' | 'h3' | 'h4' };

export function Card({ title, as: Heading = 'h3' }: Props) {
  return (
    <div className="card">
      <Heading className="card-title">{title}</Heading>
    </div>
  );
}

Now a page that needs the card one level up passes as="h2", and the visual styling stays on the class rather than the tag - which is the whole point of mistake number three above.

§ try this tool
Heading Structure Checker
Analyze your H1-H6 heading hierarchy for SEO best practices.
try it free →

Why this matters for accessibility

Heading structure isn't just an SEO concern - it's an accessibility requirement. WCAG 2.1 Success Criterion 1.3.1 (Info and Relationships) requires that information conveyed through presentation (like headings) also be programmatically determinable.

Screen reader users navigate pages primarily through headings. If your heading hierarchy is broken:

  • They can't get an overview of the page content
  • They can't jump to the section they need
  • They may miss important content entirely
  • Your site fails WCAG compliance

How screen reader users actually navigate

This is not theoretical. Screen reader users rarely read a page top to bottom. They navigate by structure, and headings are the primary mechanism:

  • NVDA and JAWS jump to the next heading with the H key, and to a specific level with the number keys - 2 for the next h2, and so on. A skipped level means a keystroke that lands nowhere.
  • VoiceOver offers a rotor (VO + U) listing every heading on the page as a navigable menu. That menu is literally your heading outline. If it reads as a jumble, so does your page.
  • Screen reader surveys have consistently found that navigating by headings is the most common way users orient themselves on an unfamiliar page, ahead of landmarks and links.

An empty heading shows up in that rotor as a blank row. A heading used for visual emphasis puts a non-section in the table of contents. Both actively mislead someone who is relying on the outline to decide where to go.

Checking your heading structure

If you want to check a single page without any tooling, paste this into the browser console:

// Prints the heading outline and flags skipped levels
let prev = 0;
document.querySelectorAll('h1,h2,h3,h4,h5,h6').forEach((h) => {
  const level = Number(h.tagName[1]);
  const text = h.textContent.trim();
  const skip = prev && level > prev + 1 ? '  <-- SKIPPED LEVEL' : '';
  const empty = !text ? '  <-- EMPTY' : '';
  console.log(`${'  '.repeat(level - 1)}h${level}: ${text || '(empty)'}${skip}${empty}`);
  prev = level;
});
console.log(`h1 count: ${document.querySelectorAll('h1').length}`);

That covers one page in one browser. Across a whole site it's tedious, and it won't catch headings injected after hydration. The LintPage Heading Structure Checker shows you every heading on any page in a hierarchical view, instantly flagging:

  • Missing H1 tags
  • Multiple H1 tags
  • Skipped heading levels
  • Empty headings
  • Overall structure quality

Run your important pages through it now. Heading issues are some of the easiest SEO and accessibility wins to fix - most are just a matter of changing one HTML tag.

Broken headings rarely travel alone. If you're auditing a page for the first time, work through the full step-by-step SEO audit, and if you're about to ship, check the SEO mistakes that kill a site on launch day - a broken heading hierarchy is number five on that list.

§ about the author
Marius OrzaruFounder, LintPage (BludeskSoft)

I built LintPage after a single stray noindex tag slipped into production and quietly cost us 47 days of organic traffic. It now runs the 60 automated checks I wish we had run before that deploy.

LinkedIn →

Get notified when we publish new posts.

§ run all 60 checks at once

Want the full picture? Stop checking one thing at a time.

Get a complete pre-launch SEO audit of your site with a single click.

run a full audit →
lintpage

Pre-launch SEO linting for developers. Catch disasters before they ship.

Product

  • Overview
  • Pre-launch checks
  • Full audit

Free tools

  • Meta tag checker
  • Robots.txt validator
  • AI crawler checker
  • OG preview
  • Sitemap validator
  • Heading checker
  • SSL checker
  • Redirect checker
  • Structured data validator
  • Broken link checker
  • Core Web Vitals checker
  • Security headers checker
  • Canonical tag checker
  • All tools →

Resources

  • Blog
  • About
  • RSS feed
  • Contact

Legal

  • Privacy
  • Terms
© 2026 lintpage. All rights reserved.built after one too many post-mortems.