Landmark Roles and HTML5 Elements for Navigation
AI generated
A11Y
WCAG
Accessibility · WCAG · ARIA · Screen Reader Navigation
Landmark Roles and HTML5 Elements for Navigation
How header, nav, main and aside orient screen reader users

Screen reader users do not orient themselves by scrolling, but by jumping deliberately between landmarks like header, nav, main, aside and footer. Using these HTML5 elements correctly and sparingly gives blind and low vision visitors a fast overview of every page and direct access to content, while excessive or unlabeled landmarks do the opposite and make navigation noticeably harder.

17 min read Landmark Roles · ARIA · HTML5 · Screen Readers WCAG 2.2 · Magento 2.4.8 · Hyva Theme

1. Why Landmark Roles Are the Foundation of Accessible Navigation

Blind and severely low vision users do not take in a web page at a glance the way sighted visitors do, they listen through the accessibility tree in a linear fashion. Without orientation points, every page would have to be heard from top to bottom before the actual content becomes reachable. Landmark roles solve exactly this problem: they divide a page into named regions like banner, navigation, main, complementary and contentinfo, between which screen readers can jump directly using keyboard shortcuts. Anyone who uses the matching HTML5 elements gets this structure automatically, without having to set a single ARIA attribute by hand.

The WebAIM Screen Reader Survey has shown for years that landmark navigation is one of the most frequently used techniques among experienced screen reader users, right next to heading navigation. A page without a clean landmark structure forces these users to feel their way through dozens of links and text blocks just to find the main content. In Magento and Hyva stores with complex layouts made of header, mega menu, breadcrumb, sidebar filters and footer, a correct landmark structure is therefore not a nice-to-have but a basic requirement for usable navigation.

2. The Implicit ARIA Roles of HTML5 Elements at a Glance

Modern browsers automatically translate semantic HTML5 elements into ARIA landmark roles that land in the accessibility tree: <header> becomes role="banner", <nav> becomes role="navigation", <main> becomes role="main", <aside> becomes role="complementary" and <footer> becomes role="contentinfo". This mapping happens without any additional markup, as long as the elements sit in the right place in the document. Writing an explicit ARIA role such as role="banner" alongside <header> on top of that is redundant and can even confuse assistive technology if the two values are ever maintained inconsistently.

The important qualifier is "in the right place": the implicit role only applies when the element is not nested inside certain ancestor elements. <header> and <footer> lose their landmark role as soon as they sit inside <article>, <aside>, <main>, <nav> or <section>, and then become plain structural containers with no landmark status at all. The skeleton below shows a correct landmark layout for a typical page.


<!-- Semantic HTML5 skeleton: landmarks appear automatically via implicit ARIA roles -->
<body>
  <header>
    <!-- role="banner" only applies here, top-level within body -->
    <a class="skip-link" href="#maincontent">Skip to main content</a>
    <nav aria-label="Main navigation">
      <ul>
        <li><a href="/">Home</a></li>
        <li><a href="/womens">Womens</a></li>
        <li><a href="/mens">Mens</a></li>
      </ul>
    </nav>
  </header>

  <!-- Second nav landmark: needs its own aria-label, otherwise indistinguishable -->
  <nav aria-label="Breadcrumb">
    <ol>
      <li><a href="/">Home</a></li>
      <li><a href="/womens">Womens</a></li>
      <li aria-current="page">Hiking Boots</li>
    </ol>
  </nav>

  <main id="maincontent">
    <!-- role="main", exactly once per page -->
    <h1>Hiking Boot Model Alpin</h1>
    <section aria-labelledby="reviews-heading">
      <h3 id="reviews-heading">Customer Reviews</h3>
    </section>
  </main>

  <aside aria-label="Related products">
    <!-- role="complementary" -->
  </aside>

  <footer>
    <!-- role="contentinfo" only applies here, top-level within body -->
  </footer>
</body>

3. header and nav: Entry Points for Screen Reader Users

A page's <header> keeps its banner role only if it is a direct or indirect child of <body> and is not nested inside <article>, <aside>, <main> or <section>. In many Hyva templates this boundary is shifted by accident when a custom module renders the global header inside a CMS block or an extra <section> wrapper. The result: the header silently loses its banner role, and screen reader users can no longer jump straight to it, even though the markup looks visually identical.

A <nav> element always needs an aria-label whenever more than one navigation exists on the same page, for example main navigation, breadcrumb, footer navigation and a mobile category filter. Without a label, the screen reader announces every one of these landmarks only as "Navigation", indistinguishable from the others. A short, descriptive label such as aria-label="Main navigation" or aria-label="Breadcrumb" solves this completely, without changing anything about the visible design.


<!-- WRONG: two nav elements with no distinguishing label -->
<nav>
  <ul>
    <li><a href="/">Home</a></li>
    <li><a href="/contact">Contact</a></li>
  </ul>
</nav>

<main id="maincontent">
  <nav>
    <ul>
      <li><a href="/sale">Sale</a></li>
      <li><a href="/new-arrivals">New Arrivals</a></li>
    </ul>
  </nav>
</main>

<!-- RIGHT: every nav landmark gets a unique accessible name -->
<nav aria-label="Main navigation">
  <ul>
    <li><a href="/">Home</a></li>
    <li><a href="/contact">Contact</a></li>
  </ul>
</nav>

<main id="maincontent">
  <nav aria-label="Category quick links">
    <ul>
      <li><a href="/sale">Sale</a></li>
      <li><a href="/new-arrivals">New Arrivals</a></li>
    </ul>
  </nav>
</main>

4. main: The Most Important Landmark on the Page

The <main> element marks the actual content unique to the current page, and per the HTML specification it must appear exactly once per page and must not be nested inside <header>, <nav>, <aside>, <footer> or <article>. For screen reader users, main is the single most important landmark, because a single keystroke takes them straight to the relevant content without having to listen through header, mega menu and breadcrumb first. A stable id="maincontent" on the element also serves as the jump target for a classic skip link placed in the page head.

In the Hyva theme structure, Magento_Theme/templates/root.phtml already renders the <main> element centrally via columns.phtml. A common mistake with custom CMS widgets or landing page builders is that a second <main> gets created inside a CMS block, often through a carelessly copied page builder component. Two main landmarks on one page are ambiguous for screen readers: which one is the actual main content? Automated testing tools such as axe-core reliably flag this case as the rule landmark-one-main.

5. aside: Marking Up Supplementary Content Correctly

The <aside> element gets the role complementary when it is a top-level sibling of the main content, and it signals content that supplements the main content while still being understandable on its own, for example a sidebar with filter facets, related products or a newsletter hint. Not every visually separated box is automatically a good candidate for aside: advertising banners with no content relationship to the page, or purely decorative elements, do not belong in a complementary landmark, because they inflate the landmark tree without providing real orientation value.

If several <aside> elements exist on the same page, for example a filter sidebar on the category page and a separate "customers also bought" block on the product detail page, each element needs its own aria-label, exactly as with multiple nav landmarks. A screen reader user jumping between regions via the landmark list must be able to tell immediately from the label what content sits in which sidebar, without having the entire content read out loud first.

Just like <header>, <footer> keeps its implicit contentinfo role only when it sits outside <article>, <aside>, <main>, <nav> or <section>. This rule has a concrete practical benefit: the author bio block at the end of a blog article inside <article> is deliberately not a contentinfo landmark, because it is not copyright and legal information for the whole site, but article-specific metadata. The global footer with imprint, terms and contact details outside <main>, on the other hand, is exactly the case contentinfo was designed for.

This distinction is not an academic nicety, it saves screen reader users real time: through the landmark list, contentinfo reliably reaches the one global site footer, instead of forcing users to work through several identically named footer landmarks per article or product card, which would otherwise show up ten times over on a blog overview page with ten article previews.

NVDA and JAWS on Windows offer the keyboard shortcut D or Shift+D to move forward or backward to the next landmark, plus a dedicated landmark list via Insert+F7 (NVDA) or the elements list menu (JAWS), which shows all landmarks on the page with their label at a glance. VoiceOver on macOS and iOS offers an equivalent overview through the rotor, reachable with a two finger circular gesture on the trackpad or screen. In all three cases, the order and labeling of landmarks in the DOM is what determines whether that list actually makes sense.

Landmarks and skip links complement each other but do not replace one another: a skip link is the very first focusable link on the page and brings sighted keyboard users as well as screen reader users straight to the main content with a single tab press, without needing to open the landmark list at all. Landmarks themselves, by contrast, are reachable at any time through between-landmark navigation, even in the middle of reading. A visually hidden but focusable .skip-link element should therefore always be the first child of <body>.


/* Skip link: invisible until it receives keyboard focus */
.skip-link {
  position: absolute;
  top: -100%;
  left: 1rem;
  z-index: 100;
  padding: 0.75rem 1.25rem;
  background-color: #18181b;
  color: #f4f4f5;
  border-radius: 0.5rem;
  font-weight: 600;
  text-decoration: none;
  transition: top 0.15s ease-out;
}

/* Becomes visible as soon as keyboard focus reaches the link */
.skip-link:focus-visible {
  top: 1rem;
  outline: 3px solid #71717a;
  outline-offset: 2px;
}

/* Mark landmark jump targets when focus is set programmatically */
main:target,
[tabindex="-1"]:focus-visible {
  outline: none;
}

8. Avoiding Landmark Overuse and Unlabeled Duplicates

Just as harmful as missing landmarks is having too many of them. If every <div> container accidentally gets turned into a <section> with an implied region role, the landmark list of a typical e-commerce page quickly grows to twenty or more entries. For screen reader users, landmark navigation then loses its purpose as a fast orientation aid, because it effectively becomes a second, unwieldy content outline. It is worth knowing that <section> only gets the landmark role region when it has an accessible name via aria-label or aria-labelledby. A <section> without a name remains a purely structural container for screen readers, not a landmark, and should only be marked up as section when that named region is genuinely useful.

The second common mistake is several identically named, unlabeled landmarks, most often with nav and aside. Automated testing tools such as axe-core check exactly this case with the rules landmark-unique and landmark-no-duplicate-banner, and reliably raise an alert on violations. An audit report makes the problem concrete and visible before it ever affects a real user in production.


{
  "violations": [
    {
      "id": "landmark-unique",
      "impact": "moderate",
      "description": "Landmarks should have a unique role or role/label/title combination",
      "help": "Ensures landmarks are unique",
      "nodes": [
        {
          "target": ["nav:nth-of-type(2)"],
          "html": "<nav><ul>...</ul></nav>",
          "failureSummary": "Fix any of the following: Landmark has the same role as another landmark but no unique aria-label to distinguish them"
        }
      ]
    },
    {
      "id": "landmark-no-duplicate-banner",
      "impact": "moderate",
      "description": "Ensures the page has at most one banner landmark",
      "nodes": [
        {
          "target": ["header:nth-of-type(2)"],
          "failureSummary": "A second header element is being interpreted as an additional banner landmark"
        }
      ]
    }
  ]
}

9. Practical Example: Landmark Structure for an E-Commerce Page

A typical product detail page in a Magento or Hyva store combines a header with search and cart icon, a breadcrumb, main content with a product gallery and purchase options, a sidebar with related products, and a global footer. What matters is that every one of these zones gets exactly one appropriate landmark, and that types which occur more than once, such as nav and aside, are consistently labeled. A mobile off-canvas menu deserves particular attention here: it should only become visible as its own nav landmark in the accessibility tree once it is actually open, so closed, invisible menus do not needlessly inflate the landmark list.

Alpine.js, the JavaScript building block behind Hyva, is well suited to implementing this behavior without extra libraries: the menu's state drives both visibility via x-show and accessibility for assistive technology via aria-hidden at the same time.


// Hyva Alpine.js: toggling a mobile off-canvas menu as a proper nav landmark
document.addEventListener('alpine:init', () => {
  Alpine.data('mobileNav', () => ({
    open: false,

    toggle() {
      this.open = !this.open;
      // Move focus into the landmark as soon as it becomes visible
      if (this.open) {
        this.$nextTick(() => this.$refs.mobileNavPanel.focus());
      }
    },

    close() {
      this.open = false;
    }
  }));
});
Element Common Mistake Correct Pattern Effect for Screen Readers
header Nested in section/article Top-level within body banner role is preserved
nav Multiple nav with no label aria-label per nav Landmarks become distinguishable
main Two main elements Exactly one main with id Unambiguous jump target
aside Ad banner marked as aside Only genuinely related boxes Landmark list stays relevant
footer One footer per article card footer only global, top-level One contentinfo per page
section div swapped out for section section only with aria-labelledby No landmark inflation

Mironsoft

Accessible navigation, landmark audits and Hyva implementation for Magento stores

Want your landmark structure reviewed by professionals?

We analyze the landmark structure of your Magento or Hyva store, uncover duplicate and unlabeled landmarks, and implement clean, WCAG-compliant navigation for screen reader users.

Landmark Audit

axe-core scan and manual screen reader testing with NVDA and VoiceOver

Hyva Implementation

Rebuild layout templates for correct header/nav/main/aside/footer structure

Skip Links & Focus

Implement skip link patterns and focus management for off-canvas menus

10. Summary

Landmark roles and HTML5 elements solve a central orientation problem: without named regions like banner, navigation, main, complementary and contentinfo, screen reader users would have to listen through every page linearly from top to bottom. <header>, <nav>, <main>, <aside> and <footer> deliver this structure automatically through implicit ARIA roles, as long as they sit in the right place in the document and are not nested inside the wrong parent elements. Landmark types that occur more than once, such as nav and aside, absolutely need a unique aria-label so they stay distinguishable in the landmark list.

Just as important as correct usage is restraint: landmark overuse through arbitrarily named section elements makes navigation just as laborious for screen reader users as having no landmarks at all. Automated tools like axe-core with the rules landmark-unique, landmark-one-main and landmark-no-duplicate-banner reliably catch the most common violations, but they do not replace a manual test with a real screen reader such as NVDA or VoiceOver.

Landmark Roles and HTML5 Elements for Navigation, the key takeaways

Use implicit roles

header, nav, main, aside, footer automatically produce banner, navigation, main, complementary, contentinfo, no extra ARIA needed.

Watch nesting

header and footer lose their role inside article, aside, main, nav or section. Only top-level within body counts.

Label duplicates

Multiple nav or aside on one page each need a unique aria-label, otherwise they are indistinguishable.

Avoid overuse

Only one main per page, section only with aria-labelledby. Too many landmarks are just as harmful as too few.

11. FAQ: Landmark Roles and HTML5 Elements for Navigation

1What is an ARIA landmark role?
A named page region such as banner, navigation, main, complementary or contentinfo. Screen readers jump directly between regions instead of reading linearly.
2What implicit roles do header, nav, main, aside and footer have?
header becomes banner, nav becomes navigation, main becomes main, aside becomes complementary, footer becomes contentinfo. Automatic, no extra ARIA attribute needed.
3Why does header sometimes lose the banner role?
Only top-level within body counts. Inside article, aside, main, nav or section, header becomes a plain container with no landmark.
4Does every page need exactly one main element?
Yes, exactly one. Two main elements are ambiguous and get flagged by axe-core as a landmark-one-main error.
5When does a nav element need an aria-label?
As soon as more than one nav landmark exists. Without a label, all of them are indistinguishable as just Navigation.
6What happens with too many landmarks on a page?
The list becomes unwieldy and loses its orientation value. section only gets a landmark role with an aria-label or aria-labelledby.
7How do screen reader users jump between landmarks?
NVDA: D/Shift+D, Insert+F7. JAWS: R and elements list. VoiceOver: rotor via a two finger circular gesture. All show the full landmark list with labels.
8What is the difference between a skip link and landmark navigation?
A skip link is the first focusable link, one tab press to the main content. Landmark navigation is reachable any time via a keyboard shortcut and lists every region.
9Does footer lose the contentinfo role inside article?
Yes, on purpose. An author footer inside article holds article-specific metadata, not the site's global information.
10How do I test landmark structure automatically?
axe-core with landmark-unique, landmark-one-main and landmark-no-duplicate-banner. Always also test manually with NVDA or VoiceOver.