HTML landmarks identify the major regions of a page so assistive technology can expose its high-level structure. Use native elements such as header, nav, main, aside, and footer, label repeated regions, and test the rendered page before launch. A layout can look orderly in CSS while remaining an undifferentiated stack of div elements in the accessibility tree.
This guide shows how to build a useful landmark structure, avoid duplicate or noisy regions, and add a focused production check without treating automated evidence as accessibility certification.
HTML landmarks checklist
Use this sequence on each representative page template:
- Put the page's unique content inside one visible
mainelement. - Use
navonly for meaningful groups of navigation links. - Label multiple navigation landmarks so their purposes are distinguishable.
- Keep the site-wide
headerandfooterat the top level when they should expose banner and content-information landmarks. - Use
aside, namedsection,form, or search regions only when the content has a clear independent purpose. - Prefer native HTML landmark elements to a generic
divplus an ARIA role. - Inspect the rendered accessibility tree, not only the source template.
- Test headings, keyboard flow, and bypass navigation separately.
- Repeat the check on important routes and responsive states.
The goal is not to maximize the landmark count. It is to give the page a short, accurate map.
Understand what HTML landmarks do
Landmarks describe large page regions such as the main content, navigation, search, and complementary information. The W3C Landmarks Pattern explains that these regions let supporting assistive technology present and navigate the high-level page structure. Several native HTML elements create landmark roles automatically: main creates a main landmark and nav creates a navigation landmark.
Landmarks do not replace headings. A landmark says what kind of region this is; a heading says what a specific section is about. Keep both structures useful. The HTML heading structure guide covers the document outline and heading-level checks that belong beside this test.
Landmarks also do not make every visitor task keyboard accessible. A skip link can move focus past repeated navigation, while landmarks give supporting tools another way to move among regions. Treat the two as complementary controls.
Start with native HTML landmark elements
A practical page shell can stay simple:
<a href="#main-content">Skip to main content</a>
<header>
<a href="/">Northstar Docs</a>
<nav aria-label="Primary">
<a href="/docs">Documentation</a>
<a href="/examples">Examples</a>
<a href="/support">Support</a>
</nav>
</header>
<main id="main-content">
<h1>Deploy the API client</h1>
<p>Follow these steps to publish the client.</p>
<nav aria-label="On this page">
<a href="#configure">Configure</a>
<a href="#deploy">Deploy</a>
</nav>
<section aria-labelledby="configure">
<h2 id="configure">Configure the client</h2>
<p>...</p>
</section>
</main>
<footer>
<a href="/status">Service status</a>
<a href="/privacy">Privacy</a>
</footer>
This creates a top-level banner from header, two named navigation landmarks, one main landmark, and a content-information landmark from footer. The W3C Page Regions tutorial documents the native element mappings and recommends labels when a page has multiple navigation menus.
Native HTML keeps the markup readable and supplies built-in semantics. The W3C ARIA in HTML specification says that explicitly restating an element's implicit role is generally not recommended. Write <nav> instead of <nav role="navigation">, and <main> instead of <div role="main">, unless a specific legacy constraint has been tested and documented.
Keep one visible main landmark
The main element contains the page's dominant, page-specific content. Site navigation, logos, repeated sidebars, and copyright information normally sit outside it. MDN's `main` element reference states that a document must not have more than one main element without the hidden attribute.
This matters in component frameworks. A persistent application shell may render one main while a route component renders another. Both can remain in the DOM during a transition, or a visually hidden old route can stay exposed to assistive technology. Test after navigation and hydration, not only in the server template.
If multiple views must remain mounted, only the active view should supply the active main landmark. A hidden inactive view should actually be hidden from rendering and interaction; shifting main onto every content card creates an inaccurate page map.
Label repeated navigation landmarks
A page can have primary navigation, account navigation, breadcrumb navigation, and an on-page table of contents. Those are valid navigation regions when each group helps visitors move through the site or document. The problem is presenting four identical entries named only "navigation."
Use aria-label when the region has no visible heading:
<nav aria-label="Primary">...</nav>
<nav aria-label="Breadcrumb">...</nav>
Use aria-labelledby when a visible heading already names the region:
<nav aria-labelledby="article-navigation">
<h2 id="article-navigation">In this guide</h2>
...
</nav>
The W3C Navigation Landmark example recommends unique labels when multiple navigation landmarks have different link sets. If two landmarks contain the same link set, such as matching navigation at the top and bottom of a page, the guidance recommends using the same label for both.
Keep labels concise and omit the role word. aria-label="Primary" is usually clearer than aria-label="Primary navigation" because assistive technology can announce the role itself. Then verify the computed name rather than assuming the attribute produced the intended result. The accessible name guide explains how aria-label, aria-labelledby, and visible text contribute to names.
Avoid common landmark mistakes
Check for these problems before release:
- A page made only from generic containers. CSS class names such as
header,sidebar, andcontentdo not create landmark semantics. - Several visible main landmarks. Keep one active
mainfor the document's dominant content. - Every section promoted to a region. Too many landmarks make the page map harder to scan. A
sectionneeds an accessible name before it is exposed as a region landmark, and not every visual panel deserves that status. - Repeated landmarks without useful names. Two
navelements with no distinguishing label force users to inspect each one. - A nested header or footer mistaken for a site landmark. A
headerorfooterinsidearticle,section,main,aside, ornavdescribes that section; it does not expose the same top-level banner or content-information landmark. - Redundant or conflicting ARIA. Do not add
role="main"tomain, and never use the abstractrole="landmark"value in page content. - Landmarks used as a compliance shortcut. Presence alone does not prove that labels are accurate, content is in the correct region, focus order works, or the page is understandable.
The broader accessibility checks before launch adds labels, contrast, keyboard flow, responsive layout, and manual review to this structural check.
Test HTML landmarks in the browser
Open the deployed URL and inspect the accessibility tree in browser developer tools. Confirm that the regions and computed names match the visible page. Then use a screen reader's landmark navigation on at least one representative route if that is part of your release process.
Ask concrete questions:
- Is there exactly one visible main landmark?
- Does the main landmark contain the page's unique content and H1?
- Are meaningful site and page navigation groups exposed as navigation landmarks?
- Can repeated navigation regions be distinguished by name?
- Are the top-level banner and content-information regions exposed where expected?
- Did client rendering add duplicates or remove a region?
- Does the structure still make sense after opening a menu or changing routes?
Test the rendered DOM because conditional components, portals, route transitions, and hydration can change the structure after the initial HTML response.
Add an HTML landmarks test to Playwright
For a route with a known shell, explicit role assertions produce useful failures:
import { expect, test } from "@playwright/test";
test("docs page exposes the expected landmarks", async ({ page }) => {
await page.goto("https://example.com/docs/deploy");
await expect(page.getByRole("main")).toHaveCount(1);
await expect(
page.getByRole("navigation", { name: "Primary" }),
).toHaveCount(1);
await expect(
page.getByRole("navigation", { name: "On this page" }),
).toHaveCount(1);
await expect(page.getByRole("banner")).toHaveCount(1);
await expect(page.getByRole("contentinfo")).toHaveCount(1);
});
Do not turn this into a universal assertion that every route needs the same regions. A focused landing page may not need an on-page navigation landmark; an embedded document can have a different shell. Define expectations by template and visitor task.
Add an automated accessibility scan for other detectable issues, but keep manual checks. Playwright's accessibility testing documentation explicitly notes that automated tests find only some accessibility problems and recommends combining them with manual assessment and inclusive user testing.
The website navigation testing checklist covers link destinations, menu behavior, labels, responsive states, and failure recovery. Keep those interaction checks beside the structural assertions.
Check HTML landmarks with Slop Audit
Run a Slop Audit on the deployed page after the landmark structure is published. During its rendered browser pass, Slop Audit counts elements matching header or [role="banner"], nav or [role="navigation"], main or [role="main"], and footer or [role="contentinfo"]. Its landmark-semantics check records the observed counts and warns when navigation or main matches are missing. This gives you URL-specific production evidence rather than a claim based only on source code.
The check is intentionally bounded. It does not validate whether a nested header or footer maps to a landmark, prove that every region contains the right content, validate unique names for repeated landmarks, exercise a screen reader, verify a skip link, or certify WCAG conformance. Browser Run capacity must also be available for rendered evidence. Use the report to find missing structure, then keep Playwright assertions and human review for meaning and interaction.
HTML landmarks release sign-off
- One visible main landmark contains the page's unique content.
- Site and page navigation groups use
navonly where navigation is their purpose. - Repeated navigation landmarks have accurate, distinguishable names.
- Top-level
headerandfooterelements expose the intended page regions. - Native HTML supplies semantics without redundant or conflicting ARIA.
- Headings and landmarks describe the same page structure at different levels.
- The rendered accessibility tree has been checked after hydration and route changes.
- Stable expectations run in CI, and the deployed URL is checked again after release.
HTML landmarks work best as a concise page map. Keep the regions meaningful, name the repeated ones, and verify the structure that users actually receive.