asw/site/content/articles/html-landmarks.md
Ludo 910b0e42a6
refactor: restructure repo into src/ site/ dist/ vendor/ packs/
Separate framework source from website:
- src/layers/ + src/main.css: CSS framework source (was assets/css/)
- site/: Hugo website (content/, layouts/, hugo.toml)
- dist/: built output (asw.css, asw.min.css)
- vendor/open-props/: vendored dependency with version tracking
- Hugo module mounts: dist/ → static, site runs from site/

Build: hugo --source site/ passes (105 pages).
npm run build produces dist/asw.css.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 15:12:42 +02:00

3.2 KiB

title description date type tags ai-disclosure ai-model ai-provider
HTML Landmark Elements The full set of semantic HTML landmarks, their ARIA roles, and when context changes their meaning. 2026-04-11 article
semantic-html
html
reference
generated claude-sonnet-4-6 Anthropic

The full set: <header>, <nav>, <main>, <article>, <section>, <aside>, <footer>, plus the newer <search>.

Each maps to an implicit ARIA landmark role, which is what makes them meaningful to screen readers and search engines — not just visual styling hooks.

<header>

Introductory content for its nearest sectioning ancestor. At the top level of <body> it maps to the banner landmark — the site identity zone. Inside an <article> or <section> it's just a local header with no landmark role.

<nav>

A block of navigation links. Maps to the navigation landmark. A page can have multiple — give each a distinct aria-label (aria-label="Primary", aria-label="Breadcrumb") so screen reader users can tell them apart.

<main>

One per page. The dominant content — excludes site chrome (nav, sidebar, footer). Maps to the main landmark. Skip-to-content links target this. Never nest <main> inside another landmark.

<article>

Self-contained, independently distributable content. A blog post, a comment, a card, a widget — anything that would make sense pulled out of context and published elsewhere. Maps to the article role. Can nest: comments inside a post are valid nested <article> elements.

<section>

A thematic grouping within a document. Only gets a landmark role (region) when given an accessible name via aria-labelledby or aria-label. Without a name it's an anonymous grouping — semantically inert, like a smarter <div>.

<aside>

Content tangentially related to the surrounding content. Sidebar, pull quote, callout, related links. Maps to the complementary landmark. The relationship is adjacent, not nested — an <aside> inside an <article> is tangential to that article, not the whole page.

Closing content for its nearest sectioning ancestor. At the body level it maps to the contentinfo landmark — copyright, legal, site-wide links. Inside an <article> it's a local footer (author, date, tags) with no landmark role.

Added in the WHATWG HTML living standard in 2023. Maps to the search landmark. Previously you had to write <form role="search">. Use it to wrap any search form or filtering UI.

The landmark map

body
├── <header>          → banner
├── <nav>             → navigation
├── <main>            → main
│   ├── <article>     → article
│   │   ├── <header>  → (no landmark — local)
│   │   ├── <section> → region (only if named)
│   │   └── <footer>  → (no landmark — local)
│   └── <aside>       → complementary
├── <search>          → search
└── <footer>          → contentinfo

The contextual rule is consistent: <header> and <footer> carry landmark roles only when they are direct children of <body>. Inside <article> or <section> they lose the landmark and become purely structural.