Landmark Elements
header, nav, main, aside, footer landmarks — how AT users jump sections, labeling multiple navs, and common landmark mistakes.
- html
- landmarks
- a11y
Landmark elements map to regions in the accessibility tree so users can skip around a page without tabbing every link. HTML gives you most landmarks for free via semantic tags.
Docs: MDN sections and outlines, WAI page structure, ARIA landmarks.
Core landmarks
| Element | Typical landmark role | Notes |
|---|---|---|
<header> |
banner (when not nested in sectioning content) | Site or page header |
<nav> |
navigation | Label if more than one |
<main> |
main | Exactly one visible main |
<aside> |
complementary | Sidebars, related |
<footer> |
contentinfo (top-level) | Site footer |
<form> |
form (when named) | Needs accessible name to be a landmark |
<section> |
region (when named) | Otherwise weak/no landmark |
<body>
<a class="skip-link" href="#main">Skip to content</a>
<header>
<p class="logo">Frontend Beauty</p>
<nav aria-label="Primary">
<ul>…</ul>
</nav>
</header>
<main id="main">
<h1>…</h1>
…
</main>
<aside aria-label="Related articles">…</aside>
<footer>…</footer>
</body>
Labeling multiple navs
<nav aria-label="Primary">…</nav>
<nav aria-label="Footer">…</nav>
<nav aria-labelledby="on-this-page-title">
<h2 id="on-this-page-title">On this page</h2>
…
</nav>
Unlabeled multiple navs all announce as “navigation” — users can’t distinguish them.
One main
<!-- Layout component mistake -->
<main>{children}</main>
<!-- nested route also wraps main → two mains -->
Enforce a single <main> in the root layout. Nested pages contribute content inside it.
section vs region
<section aria-labelledby="pricing-heading">
<h2 id="pricing-heading">Pricing</h2>
…
</section>
A bare <section> without a name often does not expose a useful landmark. Prefer headings + labeled sections when you want jump targets.
Skip links still matter
Landmarks help AT users with landmark navigation; keyboard users without SR still need a skip link to bypass repetitive header chrome.
Common mistakes
divsoup with CSS grid that looks like a layout but has no landmarks.- Multiple banners from nested headers.
- Footer inside another contentinfo nesting confusion.
- Using
role="main"on a div when<main>exists — redundant or conflicting. - Labeling every section “region” until the landmark list is noise.
Interview out-loud
“Landmarks come from elements like header, nav, main, aside, footer. I use one main, label multiple navs, and give forms/sections names when they should appear as regions. Skip links complement landmarks for keyboard users. I avoid fake layouts made only of divs.”
Footguns
- Two mains from nested layouts.
- Unlabeled nav clusters.
asidefor unrelated marketing popovers (wrong semantics).- Overusing complementary landmarks.
- Hiding main content off-screen but leaving it in the tree without care.
App shell example
<body>
<a class="skip-link" href="#main">Skip to content</a>
<header>…logo…</header>
<div class="shell">
<nav aria-label="Product">…</nav>
<main id="main">{children}</main>
<aside aria-label="Help">{help}</aside>
</div>
<footer>…</footer>
</body>
The flex/grid wrapper div.shell is layout-only — correct. Landmarks remain the semantic children. Avoid putting role="navigation" on the wrapper and another nav inside (duplicate).
Landmark noise
Too many landmarks make the rotor list useless. Do not mark every card as a region. Reserve landmarks for major page areas. Name regions only when the name helps disambiguate. A single well-structured main with good headings often beats a dozen role="region" wrappers.
Related
Further reading
Related guides
- Accessibility Tree OverviewHow browsers build the accessibility tree from DOM and CSS — roles, names, states, what’s pruned, and how to inspect it in DevTools.
- Images alt and DecorativeWrite useful alt text, mark decorative images correctly, and avoid SEO/a11y anti-patterns like keyword stuffing or missing alt.
- Tables for Tabular DataUse tables for data grids — th/scope, captions, headers, responsive strategies, and when CSS grid is the wrong substitute.
- Semantic HTMLPick elements for meaning, not looks — landmarks, headings, forms, media, and how semantics feed a11y and SEO.
- Audio and Video ElementsNative audio/video — controls, sources, captions, autoplay policies, and accessibility requirements for media on the web.