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>).
<nav> wraps navigation links
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> scope to their container
<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.