Landmarks: contain all page content
Last updated:
Related Guides
All page content must be inside landmarks without stray elements
Every piece of page content (except a skip link) must live inside a landmark region such as header, nav, main, aside, or footer.
This issue appears when text, widgets, or components are placed outside landmarks, making page structure unclear for assistive technologies.
Screen reader and keyboard users rely on landmarks to jump to major sections quickly.
Why It Matters
Landmarks give screen reader users a fast way to move between top-level sections. If content sits outside these regions, it can be missed or hard to find.
Clear landmarks reduce cognitive load by exposing predictable structure (banner, navigation, main content, complementary info, footer).
Good landmark use supports WCAG 2.2 success criteria, including Info and Relationships (1.3.1) and Bypass Blocks (2.4.1).
Common Causes
- Missing a main element, so the primary content has no landmark.
- Placing content directly in body without any landmark wrapper.
- Using multiple main elements or multiple banners/footers on a single page.
- Relying only on generic divs without landmark roles or semantic HTML.
- Injecting sticky bars, chat widgets, or modals outside landmark containers.
- Multiple navigation areas without unique labels, making them indistinguishable.
How to Fix
- Prefer semantic HTML5 landmarks:
- header (page-level banner), nav (navigation), main (primary content), aside (complementary), footer (contentinfo), form/search where applicable.
- Ensure one main landmark per page:
- Use exactly one main element. Do not nest it.
- Use top-level header and footer for page-wide banner/contentinfo:
- header and footer act as landmarks only when they are not inside article/section.
- Label repeated landmarks:
- If you have more than one nav, add
aria-labeloraria-labelledby(e.g., "Primary navigation", "Footer navigation"). - If you use
role="region", include an accessible name.
- If you have more than one nav, add
- ARIA fallback only when needed:
- If semantic elements are not possible, use ARIA roles: banner, navigation, main, complementary, contentinfo, search, region.
- Do not duplicate roles on native landmark elements.
- Handle skip links correctly:
- Place a skip-to-content link before the header, target the main element, and make it visible on focus.
- Skip links can sit outside landmarks; other content should not.
- Keep third-party embeds within landmarks:
- Mount chat, promo bars, and similar widgets inside header, main, aside, or footer as appropriate.
Recommendation: Avoid role="application" on the page unless you are building a complex widget and fully managing keyboard and screen reader behavior.
How to Test
Keyboard check:
- Tab from the address bar: the skip link appears and moves focus to main.
- Tabbing through the page, ensure focusable elements are inside landmarks (skip link excepted).
Screen reader check:
- NVDA/JAWS: open the landmarks list or use quick nav (NVDA: D/Shift+D) to cycle landmarks.
- VoiceOver (macOS): open the Rotor, Landmarks tab; (iOS): Rotor set to Landmarks.
- Confirm: one banner, labeled nav(s), one main, any complementary regions, and one contentinfo. No important content should exist outside.
Mobile/touch check:
- iOS VoiceOver: set Rotor to Landmarks and swipe up/down to move between regions.
- Android TalkBack: use reading controls to navigate by Landmarks. Verify all major sections are present and named.
Checklist:
- All primary content is inside main.
- There is exactly one banner (header) and one contentinfo (footer) at page level.
- Each navigation landmark is clearly labeled if more than one exists.
- No orphaned content outside landmarks (except the skip link).
- Third-party widgets live inside an appropriate landmark.
- Avoid redundant ARIA roles on native landmark elements.
Good Example
!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Example with landmarks</title>
<style>
.skip-link { position:absolute; left:-9999px; top:auto; }
.skip-link:focus { left:1rem; top:1rem; background:#fff; padding:.5rem; }
</style>
</head>
<body>
<a class="skip-link" href="#main">Skip to main content</a>
<header>
<h1>Site Name</h1>
</header>
<nav aria-label="Primary navigation">
<ul><li><a href="#">Home</a></li><li><a href="#">Products</a></li></ul>
</nav>
<main id="main">
<article>
<h2>Welcome</h2>
<p>Introductory text…</p>
</article>
</main>
<aside aria-label="Related links">
<ul><li><a href="#">Support</a></li></ul>
</aside>
<footer>
<p>© Example Co.</p>
<nav aria-label="Footer navigation">
<ul><li><a href="#">Privacy</a></li></ul>
</nav>
</footer>
</body>
</html>Bad Example
!doctype html>
<html lang="en">
<head><meta charset="utf-8"><title>Bad structure</title></head>
<body>
<div>Company Title</div>
<div class="top-menu">Home | Shop | Blog</div>
<div id="promo">Limited offer!</div>
<div>
<h2>Main Heading</h2>
<p>Primary content without a main landmark.</p>
</div>
<div>© 2026 Example Co.</div>
</body>
</html>Quick Checklist
- One main landmark containing the primary content.
- Top-level header and footer used for banner and contentinfo.
- Each nav landmark is unique and labeled when multiple exist.
- No important content sits outside landmarks (skip link allowed).
- Prefer semantic HTML; use ARIA landmark roles only when needed.
- Widgets, promos, and embeds are placed inside appropriate landmarks.
- Avoid multiple mains and redundant role attributes.
- Skip link targets the main element and is visible on focus.