Search code examples
reactjsaccessibilitywai-ariaaxe

How can we fix the A11y error "All page content must be contained by landmarks" with React?


The axe accessibility rule All page content must be contained by landmarks states that all top html elements should be landmark elements, eg

<html lang="en">
    <head>
        <title>Hello</title>
    </head>
    <body>
        <header>This is the header</header>
        <nav>This is the nav</nav>
        <main>This is the main</main>
        <footer>This is the footer</footer>
    </body>
</html>

But a React project requires a root element below body (required to avoid collisions with other scripts

<html lang="en">
    <head>
        <title>Hello</title>
    </head>
    <body>
        <div id="root">
            <header>This is the header</header>
            <nav>This is the nav</nav>
            <main>This is the main</main>
            <footer>This is the footer</footer>
        </div>
    </body>
</html>

I tried to set aria-hidden="true" to my div for screen-readers to ignore it

<div id="root" aria-hidden="true">

But this raises another issue: aria-hidden elements do not contain focusable elements

I couldn't find other people discussing this issue, which makes me wonder if it's relevant at all. Is there a clean way to have a react app with landmark top elements? Or should I just ignore this specific axe rule?


Solution

  • You can safely ignore this. In terms of the accessibility tree this div will be ignored.

    Do not add aria-hidden to the root div, this will attempt to hide the whole web application from a screen reader.

    As long as the contents of your root div is correctly structured it will still be completely usable.

    The only thing I would say is make sure you have a warning that "this application requires JavaScript" fallback sat outside of your root div.

    Further info

    Here is the spec on <main> as an example. It states:-

    Contexts in which this element can be used:

    Where flow content is expected, but with no <article>, <aside>, <footer>, <header> or <nav> element ancestors.

    As the <body> and <div> elements can both accept flow content you are fine.