Skip to content

The main landmark needs to sit outside other landmarks

  • Rule: axe/landmark-main-is-top-level
  • Checks: Main landmark should not be contained in another landmark
  • WCAG: none; a best practice, not a WCAG success criterion
  • Fix class: mechanical: A fix needs no authored text or visual decision.
  • People who use a screen reader or a braille display, most of them blind.

A wrapper around <main> is a landmark, such as a named <section> or an element with role="region"

Section titled “A wrapper around <main> is a landmark, such as a named <section> or an element with role="region"”

Make the wrapper a plain <div> with no landmark role and no name, or move <main> out of it. HTML lets <main> sit only in <body>, a <div>, an unnamed <form> or a custom element, so an unnamed <section> is still the wrong wrapper.

<div class="layout">
<main>
<h1>Account settings</h1>
<p>Change your email address and password.</p>
</main>
</div>

The <main> element sits inside the site header, a navigation or a sidebar

Section titled “The <main> element sits inside the site header, a navigation or a sidebar”

Move <main> out so that it is a sibling of the header, the navigation and the footer, not a child of one of them.

<header>
<a href="/">Acme home</a>
</header>
<main>
<h1>Orders</h1>
<p>You have no open orders.</p>
</main>
<footer>
<p>Acme Inc.</p>
</footer>

Changing the page’s only <main> to a <div> to clear the rule

Section titled “Changing the page’s only <main> to a <div> to clear the rule”

The page then has no main landmark, so screen reader users cannot jump to its content, and axe reports landmark-one-main instead.

The part of the fix that differs in React, in its syntax. The rest of the guidance holds.

A layout component renders <main> around the routes, and a page component renders its own <main> inside it

Section titled “A layout component renders <main> around the routes, and a page component renders its own <main> inside it”

Keep <main> in the layout only, and have page components return their content in a fragment, a <div> or an <article>.

function Layout({ children }) {
return (
<>
<header>
<a href="/">Acme home</a>
</header>
<main>{children}</main>
</>
);
}
function OrdersPage() {
return (
<>
<h1>Orders</h1>
<p>You have no open orders.</p>
</>
);
}

The app mounts into a <main> in index.html and also renders its own

Section titled “The app mounts into a <main> in index.html and also renders its own”

Mount the app into a plain <div>, such as <div id="root">, and render <main> from the app.

axe-core’s documentation of the rule

CORA’s fix guidance adapts content from accessibility-agents, under the MIT License: see its notice.