A modern screen reader (NVDA, JAWS, VoiceOver) doesn't read your page top to bottom: it shows the list of "landmarks" — the page's main regions — and lets you jump straight to the one you want. Without landmarks, the user is forced to go through the page linearly, element by element. With them, they navigate as if with a table of contents.
The recommended skeleton
<body>
<a class="skip-link" href="#main">Skip to content</a>
<header role="banner">...</header>
<nav role="navigation" aria-label="Main">...</nav>
<main id="main" role="main">
<!-- page content -->
</main>
<aside role="complementary" aria-label="Product filters">...</aside>
<footer role="contentinfo">...</footer>
</body>The HTML5 tags (`<header>`, `<nav>`, `<main>`, `<aside>`, `<footer>`) already carry an implicit role: the explicit `role` mainly serves compatibility and clarity. The golden rule: a single `<main>`, a single `<header role="banner">` and a single `<footer role="contentinfo">` at the document level.
Naming the regions that repeat
If you have several `<nav>` elements (main, breadcrumb, pagination), give each a distinct `aria-label`: "Main", "Breadcrumb", "Pagination". Without that, the screen reader announces "navigation" three times indistinguishably, and the map loses all its value.
E-commerce specifics
- →Category page: filters in an `<aside aria-label="Filters">` next to the `<main>`
- →Product page: a single `<main>`; the "related products" block in an `<aside>`
- →Checkout: a `<form>` inside the `<main>`, with no distracting secondary nav
- →Footer: a single `<footer role="contentinfo">` at the body level, never nested inside the `<main>`
⚠ The two mistakes that break everything
First, several `<main>` elements on one page: the screen reader no longer knows where the main content is. Second, wrapping everything in `<div>`s: with no semantic tags, there's no landmark, and the region list stays empty.
Checking your map
In NVDA, the Insert+F7 key opens the list of landmarks, headings and links. If your page doesn't clearly show header / navigation / main / footer, the semantic structure needs revisiting. It's a 30-second test that instantly reveals the quality of the skeleton.
Frequently asked questions
Do I need role= if I already use <header>, <main>, etc.?
Roles are implicit with HTML5 tags, so redundant in most cases. Making them explicit does no harm and improves robustness on old screen readers. The key is to use the right semantic tags rather than `<div>`s.
How many landmarks per page, ideally?
No magic number, but stay readable: banner, navigation, main, complementary, contentinfo cover the essentials. Too many regions drowns the information as much as too few.
Must the <main> be unique across the whole SPA?
Unique per displayed view. In an SPA, at each route change there must be only one `<main>` visible at a time; moving focus to it after navigation is a good complementary practice.
Check the landmark structure of your key pages:
→ Run an audit