Development

Semantic HTML: The Quiet Foundation of SEO and Accessibility

Semantic HTML tells browsers, screen readers, search engines and AI crawlers what each part of your page means. Here is how to use landmarks, headings, native controls and text-level elements properly.

10 min readHiddlins Editorial Team

Semantic HTML is the least glamorous part of building a website and one of the most valuable. When you mark up a navigation menu with <nav>, a button with <button> and a data table with real header cells, you are not just writing tidy code: you are telling browsers, screen readers, search engines and AI crawlers what each piece of the page means. That meaning powers keyboard navigation, reader modes, featured snippets and the way assistive technology announces your content. This article explains how machines read your markup, which elements matter most, where ARIA fits, and how to audit a page in less than half an hour.

What “semantic” actually means#

In HTML, semantics is the meaning an element carries independently of how it looks. An <h2> means “a second-level heading” whether it is styled at 14 pixels or 40. A <span> styled to look exactly like a heading means nothing at all. MDN’s glossary entry on semantics puts it simply: choose the element that best describes the content, and leave presentation to CSS.

The key mental shift is that your page has at least two audiences. Sighted mouse users infer structure from visual design: big bold text is a heading, a row of links at the top is navigation, a grey box on the side is secondary. Every other consumer of your page — a screen reader, a search engine crawler, a browser’s reader mode, a voice assistant, a large language model ingesting your content — has to infer that structure from the markup. If the markup is a pile of generic <div> elements, those consumers are guessing.

How machines read your page#

The accessibility tree#

Browsers build two parallel structures from your HTML: the DOM and the accessibility tree. The accessibility tree is a simplified version of the page that exposes, for each meaningful node, a role (button, link, heading, navigation), a name (the text announced to the user), a state (expanded, checked, disabled) and sometimes a value. Screen readers, voice control software and switch devices interact with this tree, not with your pixels. Native semantic elements populate it correctly by default; generic elements contribute nothing beyond their text.

You can inspect it directly: Chrome, Edge and Firefox all have an accessibility pane in their developer tools, and Chrome offers a full-page accessibility tree view. Looking at it once is usually enough to change how you write markup.

Search engines#

Google renders pages and extracts their main content, headings, links, lists and tables. Semantic markup does not earn a ranking bonus on its own, but it reduces ambiguity: clear headings describe topics, lists and tables are easy to lift into rich results, and real links (<a href>) are what crawlers follow. A “link” built from a <div> with a click handler is invisible to a crawler.

AI crawlers and answer engines#

Generative search systems chunk pages into passages and reason about which passage answers a question. Logical heading hierarchies, self-contained sections and well-structured tables make those passages cleaner and more quotable. If being cited by AI search is a goal, semantic structure is the foundation; we cover the rest of that topic in our guide to Generative Engine Optimization.

Landmarks and document structure#

Landmarks let assistive technology users jump straight to the major regions of a page, much as sighted users glance at a layout. Most HTML sectioning elements map to an ARIA landmark role automatically:

Element Implicit role Notes
<header> banner Only when it is not inside article, aside, main, nav or section.
<nav> navigation Label multiple navs, e.g. aria-label="Primary" and aria-label="Footer".
<main> main Exactly one visible main per page.
<aside> complementary Content related to, but separable from, the main content.
<footer> contentinfo Same scoping rule as header.
<section> region Only becomes a landmark when it has an accessible name.
<form> form Only becomes a landmark when it has an accessible name.
<search> search A newer element for search and filter areas, supported in current major browsers.

A sensible skeleton for most content pages looks like this:

<body>
  <a class="skip-link" href="#content">Skip to content</a>

  <header>
    <a href="/" class="logo">Brand name</a>
    <nav aria-label="Primary">
      <ul>
        <li><a href="/services/">Services</a></li>
        <li><a href="/blog/" aria-current="page">Blog</a></li>
      </ul>
    </nav>
  </header>

  <main id="content">
    <article>
      <h1>Article title</h1>
      <p>Published <time datetime="2026-10-14">14 October 2026</time></p>
      <section aria-labelledby="setup">
        <h2 id="setup">Setting up</h2>
        …
      </section>
    </article>
    <aside aria-label="Related articles">…</aside>
  </main>

  <footer>…</footer>
</body>

The W3C’s ARIA Authoring Practices Guide has a thorough explanation of landmark regions, including how many to use. The short version: every piece of visible content should live inside some landmark, and landmarks of the same type should be distinguishable by label.

article vs section vs div#

Use <article> for self-contained content that would make sense on its own — a blog post, a product card, a comment. Use <section> for a thematic grouping that normally has its own heading. Use <div> when you need a wrapper purely for styling or layout. A <div> is not bad; it is honest. The problem is only when a <div> is used instead of an element that carries meaning.

Headings: the outline people actually use#

Headings are the single most-used navigation method for many screen reader users, who pull up a list of headings to skim a page the way sighted users scan bold text. They are also the clearest topical signal you can give a search engine. A few rules cover almost every case:

  • One h1 that names the page. The specification permits several, and Google has said multiple h1 elements are not a problem for search, but a single, descriptive h1 is the clearest convention for users.
  • Do not skip levels on the way down. An h4 directly under an h2 implies a missing level. Jumping back up (from h4 to h2) is fine.
  • Choose levels by structure, never by size. If a heading looks too big, change the CSS, not the element.
  • Do not use headings for decoration. A tagline or “eyebrow” label above a heading is a paragraph, not an h6.
Watch out

  • The old “document outline algorithm”, where each <section> restarted heading levels at h1, was never implemented by browsers or screen readers and has been removed from the HTML specification. Always use explicit heading levels.
  • Page builders often let editors pick a heading level for its visual style. Check the actual outline after content is entered, not just the template.

Native interactive elements beat custom widgets#

The most expensive semantic mistakes are interactive ones, because they lock people out entirely. A clickable <div> cannot be reached with the Tab key, does not respond to Enter or Space, and is announced as plain text. Compare:

<!-- Inaccessible: no role, not focusable, no keyboard support -->
<div class="btn" onclick="openMenu()">Menu</div>

<!-- Accessible by default: focusable, Enter/Space work, announced as a button -->
<button type="button" aria-expanded="false" aria-controls="site-menu">Menu</button>

The rule of thumb is short: links go somewhere, buttons do something. If activating it changes the URL, use <a href>. If it submits, opens, closes, toggles or filters, use <button>.

Let the platform do the heavy lifting#

HTML now covers several patterns that used to require JavaScript libraries:

  • <details> and <summary> give you an accessible disclosure widget with zero script, ideal for FAQs and “show more” sections.
  • <dialog> with showModal() gives you a modal with focus handling, the Escape key and an inert background built in.
  • The popover attribute provides non-modal overlays such as menus and tooltips, with light dismiss and top-layer rendering.

Each of these replaces dozens or hundreds of lines of custom JavaScript, which is good for accessibility and for performance. We explore this approach further in Modern JavaScript Without the Bloat.

Forms#

Forms are where semantics translate most directly into conversions. Every input needs a programmatically associated label; placeholders are not labels. Group related controls such as radio buttons with <fieldset> and <legend>. Use the correct type (email, tel, url, number) so mobile users get the right keyboard, and add autocomplete tokens so browsers can fill in names, addresses and payment details.

<form aria-labelledby="quote-title">
  <h2 id="quote-title">Request a quote</h2>

  <label for="email">Work email</label>
  <input id="email" name="email" type="email" autocomplete="email" required
         aria-describedby="email-hint">
  <p id="email-hint">We reply within one business day.</p>

  <fieldset>
    <legend>Project type</legend>
    <label><input type="radio" name="type" value="site"> Website</label>
    <label><input type="radio" name="type" value="store"> Online store</label>
  </fieldset>

  <button type="submit">Send request</button>
</form>

Text-level semantics that pay off#

Beyond structure and controls, a handful of smaller elements add meaning that both people and machines use:

  • Lists. Use <ul> and <ol> for genuine lists. Screen readers announce “list, 5 items”, which tells users how much is coming, and search engines can surface ordered steps as list snippets.
  • Tables for tabular data. Use <caption>, <thead> and <th scope="col"> or scope="row" so each cell can be announced with its headers. Never use tables for layout.
  • <time datetime> gives dates a machine-readable value, useful for publication and event dates.
  • <figure> and <figcaption> associate a caption with an image, chart or code sample.
  • <strong> and <em> express importance and stress; <b> and <i> are for stylistic offset without extra importance.
  • <blockquote> and <cite> mark quotations and the titles of cited works.
  • Alternative text. Informative images need meaningful alt text; decorative images need an empty alt="" so they are skipped.

Semantic HTML and structured data are complementary. Markup describes the role of each part of the page; schema.org JSON-LD describes the entities on it (an organization, a product, an article). You want both.

ARIA: powerful, and easy to misuse#

WAI-ARIA lets you add roles, states and properties to elements when HTML alone cannot express what a component does. It is essential for genuinely custom widgets such as tabs, comboboxes and live regions. But ARIA only changes what is announced; it adds no behaviour. Putting role="button" on a <div> does not make it focusable or keyboard-operable — you still have to add tabindex and key handlers yourself.

That is why the first rule of ARIA use is: if a native HTML element or attribute gives you the semantics and behaviour you need, use it instead. WebAIM’s annual accessibility analysis of the top million home pages has repeatedly found that pages using ARIA tend to have more detected accessibility errors than pages without it — not because ARIA is bad, but because it is so often applied incorrectly.

Patterns that are usually worth the ARIA:

  • aria-expanded on buttons that show and hide content.
  • aria-current="page" on the active navigation link.
  • aria-live="polite" regions for status messages such as “3 results found” or “Added to cart”.
  • aria-label or aria-labelledby to distinguish repeated landmarks or icon-only buttons.
  • aria-describedby to connect hints and error messages to form fields.

Semantic HTML in WordPress and page builders#

The WordPress block editor produces reasonably semantic output: heading blocks output real headings, list blocks output real lists, and the table block outputs a <table> with an optional header section and caption. Block themes define template parts for the header and footer that can be assigned the right HTML element. Most problems we find come from three places:

  • Themes that wrap the whole page in <div>s, omit <main> or render the site title as an h1 on every page.
  • Page builders that nest content in many layers of wrappers and let editors choose heading levels for visual reasons.
  • Plugins such as sliders, popups and mega menus that output click handlers on non-interactive elements.

A lean DOM also renders and updates faster, which feeds directly into your Core Web Vitals. Semantic, minimal markup is one of the rare choices that improves accessibility, SEO and performance at the same time.

A 30-minute semantic audit#

You can learn most of what you need about a page’s semantics in half an hour:

  1. Keyboard pass. Unplug the mouse. Tab through the page. Can you reach and operate every control? Is focus always visible? Does the skip link work?
  2. Headings and landmarks. Use a screen reader’s rotor or elements list, or a browser extension, to list headings and landmarks. Does the outline read like a table of contents?
  3. Accessibility tree. Inspect key components in DevTools. Does each control have the right role and a sensible name?
  4. Automated scan. Run axe or Lighthouse’s accessibility audit to catch missing labels, empty links and contrast issues. Remember that automated tools only catch a portion of problems.
  5. Validate. Run the HTML through the W3C Nu validator to catch broken nesting and duplicate IDs, which break label and ARIA relationships.

For the full picture of conformance requirements, the W3C’s WCAG overview is the reference, and our WCAG 2.2 guide for small businesses translates it into a practical plan. Semantic structure also sits near the top of our technical SEO checklist for new websites.

Key takeaways

  • Semantic HTML communicates meaning to everything that is not a sighted mouse user: assistive technology, crawlers, reader modes and AI systems.
  • Use landmarks, one descriptive h1 and a logical heading hierarchy.
  • Links go somewhere, buttons do something; prefer native button, dialog, details and popover over custom widgets.
  • Use ARIA to fill gaps, never to replace native elements.
  • Lean, semantic markup improves accessibility, SEO and performance together.

Conclusion: build the foundation first#

Semantic HTML does not show up in screenshots, which is exactly why it gets neglected. Yet it is the layer every other investment rests on: accessibility features, SEO work, structured data and performance tuning all work better on top of clean, meaningful markup — and they fight an uphill battle without it.

Every site we build starts from that foundation. If you are planning a new site or rebuilding one that has grown messy, our WordPress Website Development service delivers lean, semantic, accessible themes your editors can’t easily break. Want us to look at your current markup first? Contact us and we will tell you honestly what we find.

Frequently asked questions

Does semantic HTML improve Google rankings directly?

There is no ranking bonus for using an article or nav element as such. Semantic HTML helps indirectly: it makes your content easier to parse, makes headings, lists and tables clearer to extract, and supports the accessibility and usability that keep visitors engaged.

Is it wrong to have more than one h1 on a page?

The HTML specification allows it and Google has said multiple h1 elements do not cause problems for search. For screen reader users, however, a single h1 that names the page is the clearest convention, so we recommend one h1 followed by a logical h2 to h6 hierarchy.

When should I use ARIA instead of HTML elements?

Use ARIA only when no native HTML element or attribute provides the semantics and behaviour you need, for example for a custom tab interface or a live region. A native button, link, dialog or details element is always preferable because it brings keyboard support and correct semantics for free.

How can I check whether my page is semantically structured?

Navigate the page using only the keyboard, view the accessibility tree in your browser's developer tools, list the headings and landmarks with a screen reader or a browser extension, and run an automated checker such as axe. Automated tools catch only part of the issues, so manual checks are essential.

Written by the Hiddlins Editorial Team

We are a full-stack web development studio. Every article is researched, tested and reviewed according to our editorial policy. Questions or corrections? Tell us.

Have a project in mind?

Tell us what you are building. We reply within one business day with honest advice, a realistic timeline and a fixed-price proposal.