Skip to content

All content needs to sit inside a landmark

  • Rule: axe/region
  • Checks: All page content should be contained by landmarks
  • 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 heading, a paragraph or an image sits directly in <body>, beside the landmarks

Section titled “A heading, a paragraph or an image sits directly in <body>, beside the landmarks”

Move it into the landmark it belongs with: the page’s own content into <main>, site-wide content into the header or the footer. A skip link before the header can stay where it is.

<header>
<a href="/">Acme home</a>
</header>
<main>
<h1>Orders</h1>
<p>You have no open orders.</p>
</main>
Section titled “A cookie notice, an announcement bar or a promotion sits outside every landmark”

Put it inside the header or the footer if it is part of the site frame. If people need to find it on its own, make it a <section> with an aria-label that names it. A notice that blocks the page belongs in a modal <dialog>.

<section aria-label="Cookie consent">
<p>We use cookies to remember your settings.</p>
<button type="button">Accept cookies</button>
</section>

A <section> or a <form> outside the landmarks has no name

Section titled “A <section> or a <form> outside the landmarks has no name”

Move it into <main> or the landmark it belongs to. Neither element is a landmark without aria-label or aria-labelledby; name it only if it is a major part of the page.

Section titled “Wrapping the whole page, header and footer included, in <main>”

axe accepts it when the header and footer have no roles, but they then stop being landmarks, so screen reader users can no longer jump to them or past them.

Wrapping stray content in role="region" without a name

Section titled “Wrapping stray content in role="region" without a name”

axe counts it as a landmark, but browsers do not expose a region without a name, so screen reader users still cannot reach the content by landmark.

Adding aria-hidden="true" to the stray content

Section titled “Adding aria-hidden="true" to the stray content”

It clears the rule by hiding visible content from screen reader users.

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

Toasts or other messages are portaled into document.body

Section titled “Toasts or other messages are portaled into document.body”

Portal them into a container with role="status" that stays mounted. axe counts a live region as inside a landmark, and screen readers announce what is added to it.

function Toasts({ messages }) {
return createPortal(
<div role="status">
{messages.map((message) => (
<p key={message.id}>{message.text}</p>
))}
</div>,
document.body,
);
}

Render it as a <dialog> opened with showModal(), or as a container with role="dialog" that manages focus itself, and name it, such as with aria-labelledby pointing at its heading. axe counts a dialog as inside a landmark.

Mounting the toast container only while a message shows

Section titled “Mounting the toast container only while a message shows”

Screen readers often miss a live region that appears together with its text. Keep the container mounted and change only what is inside it.

axe-core’s documentation of the rule

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