Overview

Every HTML element carries an implicit ARIA role that assistive technology, search crawlers, and browser reader modes consume. A page of nested <div> elements gives those consumers nothing. Replace each <div> with the element that names what the region actually is, and the document becomes navigable without a single line of JavaScript.

<main> holds the page’s primary content

Use exactly one <main> per page. It wraps the content that is unique to this URL, not the chrome repeated across pages. Screen readers expose a “main” landmark that lets users jump straight to content, skipping headers and nav. Skip links work the same way: <a href="#main">Skip to content</a> anchors to this element.

<body>
  <header><!-- site chrome --></header>
  <nav><!-- primary nav --></nav>
  <main id="main">
    <!-- unique page content -->
  </main>
  <footer><!-- site footer --></footer>
</body>

<article> wraps self-contained content

Use <article> when the block makes sense on its own: a blog post, a news story, a product card, a comment. Self-contained means the content could be syndicated or embedded elsewhere without losing meaning. Articles can nest when a comment thread lives inside a post.

<article>
  <header>
    <h2>Postgres 17 Released</h2>
    <time datetime="2026-05-01">May 1, 2026</time>
  </header>
  <p>The release ships logical replication improvements...</p>
</article>

<section> groups thematic content within a page or article

Use <section> for a named thematic block that belongs to a larger whole. Every <section> needs a heading (<h2> through <h6>) so the outline is legible. Do not use <section> as a generic container; that is what <div> is for.

A section is wrong when the content is self-contained (use <article>) or when it is only there for styling (use <div>).

Use <nav> for the primary site navigation and for secondary nav blocks like a table of contents or pagination. Multiple <nav> elements are fine; give each an aria-label or aria-labelledby so users can distinguish them.

<nav aria-label="Primary">
  <ul>
    <li><a href="/">Home</a></li>
    <li><a href="/blog">Blog</a></li>
  </ul>
</nav>
<nav aria-label="Pagination">
  <a href="/page/2">Next</a>
</nav>

Do not wrap every list of links in <nav>. Footer link lists for legal pages or social icons are not navigation landmarks.

<aside> holds tangential content

Use <aside> for content that is related to the main flow but not essential to it: a pull quote, a sidebar, a related-links callout, a tip box. When <aside> is inside an <article>, it is tangential to the article. At the page level, it is tangential to the document.

Avoid using <aside> for purely decorative panels or for any content that is required to understand the main text.

<header> and <footer> are not global elements. Each scopes to its nearest sectioning element (<body>, <article>, <section>). A page can have a document header, an article header, and an article footer all at once.

<article>
  <header>
    <h2>Article Title</h2>
    <p>By Author, <time datetime="2026-05-14">May 14, 2026</time></p>
  </header>
  <p>Body...</p>
  <footer>
    <p>Tags: HTML, Semantics</p>
  </footer>
</article>

Avoid div soup; check every container

Before adding a <div>, ask what the block is. If it is primary page content, use <main>. If it is a self-contained piece, use <article>. If it is a thematic group with a heading, use <section>. If it is navigation, use <nav>. If it is tangential, use <aside>. Reserve <div> for layout containers that carry no meaning.

The benefit is concrete: screen reader users navigate by landmarks. Search crawlers weight heading text inside <article> differently from boilerplate in <header>. See html for the heading-order rules that pair with this landmark structure, and accessibility for the WCAG conformance requirements these elements satisfy. For adding ARIA on top of semantic elements, see html-aria-patterns.