HTML Headings
html headings heading elements structure content for accessibility, seo, and human scanability heading elements (h1–h6) are the primary structural signals
Introduction
Heading elements (h1–h6) are the primary structural signals for screen reader outline navigation and Google's content understanding. BBC News mandates one h1 per article with sequential h2–h4 sections; Airbnb maps listing titles to h1 in SSR HTML so crawlers and AT share the same hierarchy. Staff engineers treat headings as an API — not typography shortcuts.
Business problem
Heading chaos — multiple h1s from CMS widgets, h4 before h2 for "smaller font" — degrades SEO relevance scoring and causes lawsuit-grade a11y findings on marketing pages.
- Conversion: Shopify theme audits found hero h1 buried below promotional h2 blocks — screen reader users couldn't find product name.
- Compliance: WCAG 1.3.1 Info and Relationships requires programmatic heading structure; visual bold alone fails audits.
- SEO: Google uses headings to infer topic clusters; skipped levels dilute internal relevance on category pages.
Why this feature exists
Outline before CSS: Early HTML needed hierarchical section titles independent of presentation. Headings became the interoperable outline layer every engine, crawler, and screen reader consumes.
- History: h1–h6 fixed in HTML2; HTML5 added sectioning elements but headings remain the outline workhorse.
- Rejected: Font-size tags and div+class heading patterns failed AT and SEO — semantic tags won.
- Modern role: Design systems map component titles to correct level — React still emits h1–h6 in DOM.
Browser internals
Heading nodes are HTMLHeadingElement instances with implicit role="heading" and aria-level from tag name. Tree builder inserts headings per sectioning content models; mis-nested headings may still render but produce inconsistent accessibility tree levels.
- Accessibility tree: Level derived from tag number unless aria-level overrides (avoid overrides).
- Section association: h1 in section vs document — outline algorithms differ between AT products.
- ID reflection: heading.id enables fragment navigation — affects history and scroll anchoring.
HTMLHeadingElement → role: heading, level: 1..6Accessibility tree: flat heading list for rotor navigationDOM → getElementsByTagName('h1') for SEO lint rules
Rendering workflow
Headings are text nodes in the render tree — they participate in LCP when h1 is the largest above-the-fold text. Font loading on heading faces blocks text paint; system font stacks in critical CSS reduce delay.
- LCP: Product h1 often is LCP element on PDP — keep in initial HTML, avoid client-only render.
- CLS: Web fonts swapping on h1 cause layout shift — size-adjust or fallback metrics.
- Paint: Long heading text with text-wrap: balance changes intrinsic height — reserve min-height if needed.
Feature deep dive
Rules: One h1 per page (or per logical document in SPA route). Don't skip levels for styling — use CSS. Nest sections with section/article and place headings as first meaningful child.
- h1: Page topic — listing title, article headline, dashboard name.
- h2–h3: Major and minor sections — filters, specs, reviews on Amazon PDP.
- Hidden headings: Visually hidden h2 acceptable for landmark labels — not display:none on critical outline nodes.
<main><h1>Stripe Atlas — Incorporate your startup</h1><section aria-labelledby="pricing-heading"><h2 id="pricing-heading">Pricing</h2><h3>Standard plan</h3><p>Includes registered agent and tax ID support.</p></section></main>
Accessibility analysis
Screen reader rotor lists headings for jump navigation — BBC engineers test every template with NVDA heading list. Empty headings (CMS placeholders) pollute the list and violate WCAG 2.4.6.
- Outline: VoiceOver and JAWS expose heading level — h1→h4 skip confuses "where am I?"
- Keyboard: Headings aren't focusable unless tabindex added — prefer skip links to h1/main.
- WCAG: 2.4.10 Section Headings — use headings to organize content, not decorative spans.
SEO impact
Google guidance: Use headings to emphasize main topics — not to stuff keywords. Amazon category pages use h2 per facet group; duplicate h1 on paginated URLs get canonical consolidation.
- Snippet context: Headings near query terms influence relevance — not a direct ranking knob but aids understanding.
- Featured snippets: FAQ h2/h3 structure helps extraction when paired with concise paragraphs.
- JS rendering: Headings injected late may miss first crawl wave — SSR h1 is safer.
Security considerations
User-generated headings in forums and reviews are XSS vectors when echoed unescaped. CMS must encode text content in h* tags; CSP blocks inline script from compromised heading fields.
- XSS: <h2> onerror via broken sanitizer — allowlist tags, encode text.
- Anchor hijack: id on headings from user input can overwrite existing fragments — sanitize ids.
- Phishing: Fake h1 "Verify your Stripe account" in injected HTML — sanitize UGC.
Performance impact
Heading count barely affects DOM size, but heading-driven accordion components often bundle heavy JS. Prefer native details/summary or CSS for collapse — keep headings static in HTML.
- LCP: Hero h1 with custom font — preload woff2 if h1 is LCP.
- INP: SPA route changes should move focus or announce new h1 — don't block main thread.
- HTML weight: Keyword-stuffed long h1 strings bloat TTFB on mobile — keep concise.
Real production example
Airbnb listing page pattern: SSR emits single h1 with listing title; amenities and reviews use h2; subsections h3. Heading text matches JSON-LD name where applicable.
- Template lint: CI fails if more than one h1 in static HTML output.
- CMS: Authors pick heading level from dropdown — not font size.
- i18n: RTL headings inherit dir from html — no separate markup per locale.
<article><h1>Loft in Shoreditch — 2 guests</h1><section><h2>About this space</h2>…</section><section><h2>Reviews</h2>…</section></article>
Enterprise usage
Design systems at Google and Shopify document Heading components with enforced level prop and forbidden patterns (no h1 in cards). CMS templates cap maximum depth at h4 for body content.
- Storybook: Heading stories show level 1–4 with accessibility notes.
- CI: axe heading-order rule + custom eslint for React heading level props.
- Governance: SEO team reviews heading changes on money pages.
Common production failures
Marketing A/B test swapped h1 for styled h3 "for design" — organic traffic on landing pages dropped 18% over six weeks; screen reader outline showed five top-level topics.
- Incident: WYSIWYG allowed h1 in every block — 14 h1s on homepage.
- SEO: SPA forgot to update h1 on client navigation — all routes announced same title to Google.
- A11y lawsuit: Help center articles skipped from h2 to h5 — settlement included heading remediation.
Architecture review questions
- Is there exactly one h1 representing the primary page topic in initial HTML?
- Do heading levels increase by one without skips for styling convenience?
- What does the screen reader heading rotor show for this template?
- Are user-generated headings encoded and sanitized?
- Does the h1 appear in SSR HTML for crawler-first indexing?
- Are web fonts on headings accounted for in LCP and CLS budgets?
Hands-on project
Remediate a marketing page with heading violations: fix hierarchy, add visually hidden section headings where needed, verify rotor navigation, and measure Lighthouse SEO delta.
- Deliverable: Before/after heading map table in PR.
- Verify: NVDA heading list matches visual outline.
- Stretch: Add CI rule blocking h1 inside reusable card components.
Interview questions
How do you decide h1 ownership in a micro-frontend shell with multiple teams?(Advanced)
Shell owns document h1 for route title; MFEs use h2+ only. Contract tested in integration HTML snapshots. SPA navigation updates h1 text and document.title together. Google sees one h1 per URL in SSR output.
Follow-up: What about modals with their own title?
Explain the difference between HTML5 outline and screen reader heading navigation.(Advanced)
Document outline algorithms had inconsistent AT adoption; real-world a11y relies on heading level numbers in DOM order. Staff optimize for rotor/jump lists — sequential h1–h6 — not theoretical outline without h2.
Follow-up: When is aria-level justified?
How would heading structure affect Google's understanding of an e-commerce category page?(Advanced)
h1 names category; h2 groups facets, buying guides, FAQs. Keyword stuffing in headings hurts quality signals. Internal links in section headings distribute PageRank. Paginated h1 duplication needs canonical strategy.
Follow-up: Do headings directly rank keywords?
Try it yourself
Edit the HTML, CSS, or JS panels — the preview updates as you type.
Try it yourself
Summary
Heading elements structure content for accessibility, SEO, and human scanability. Production teams at BBC and Airbnb scale enforce one h1, logical levels, and SSR-visible hierarchy — validated in CI, not fixed after audit failure.