ADA Compliance Professionals

    Main landmark must be unique per page

    Last updated:

    Who it helps:
    Blind
    Cognitive
    Standard:
    WCAG 2.2 Level A

    Use exactly one main landmark per page; iframes may have zero or one

    Intro:

    Use one main landmark to identify the primary content of a page. Top‑level documents should have a single main; each iframe document should contain either none (for non-document content) or a single main. This improves navigation for assistive technology users and reduces confusion.

    Why It Matters

    Screen reader users jump between landmark regions to reach key areas quickly. Multiple mains fragment the primary content and make the landmarks list noisy or misleading. Missing a main makes it harder to find the core content.

    Clear landmark structure also aids users with cognitive disabilities by providing predictable page regions. It benefits power users who rely on quick navigation features.

    Common Causes

    • Using <main> more than once in a page template or across includes.
    • Adding role="main" to a container while also using a native <main>.
    • Nesting <main> inside article, aside, header, footer, or another main.
    • Third‑party widgets or CMS blocks that inject an extra role="main".
    • Iframes that include multiple mains, or a role="main" plus <main>.
    • Single‑page apps that mount multiple root views each with their own main.

    How to Fix

    • Ensure exactly one <main> element in the top‑level document. Do not use role="main" elsewhere.
    • Place <main> as a sibling to header/nav/footer, not inside them. Do not nest main within article, aside, header, footer, nav, or another main.
    • If a legacy template uses role="main" on a non-main element, replace it with a single <main> and remove other role="main" occurrences.
    • For multiple navigation areas, keep them as nav elements and add aria-label (for example, aria-label="Primary" and aria-label="Footer").
    • Iframes:
    • If an iframe hosts a full document with primary content, include one main inside the iframe’s document.
    • If an iframe is a widget/advertisement/media player without distinct primary content, use no main inside that iframe.
    • Add a descriptive title attribute to each iframe so users know what it contains.
    • Single‑page apps: keep one persistent <main> and update its contents rather than creating additional mains on route changes.
    • Recommendation: prefer native HTML landmarks (header, nav, main, footer) and use ARIA roles only when no native element exists.

    How to Test

    • Keyboard check:
    • If you provide a skip link, Tab to it and confirm it moves focus into the main region. Landmarks do not replace skip links for keyboard users.
    • Screen reader check:
    • NVDA/JAWS (Windows): Open the landmarks list and confirm there is exactly one Main in the top‑level document. Enter iframes and re-check that each has zero or one Main.
    • VoiceOver (macOS/iOS): Use the rotor to list landmarks and verify a single Main per document/frame.
    • TalkBack (Android): Use local context menu to navigate landmarks and verify counts.
    • Visual/DevTools check:
    • Search the DOM for <main> and [role="main"]. There should be exactly one occurrence per document.
    • Use browser Accessibility pane or an automated checker to flag multiple or missing mains.

    Good Example

    HTML
    !doctype html>
    <html lang="en">
    <head>
      <meta charset="utf-8">
      <title>Sample Page</title>
    </head>
    <body>
      <header>
        <a class="skip-link" href="#content">Skip to main content</a>
        <h1>Acme News</h1>
      </header>
    
      <nav aria-label="Primary">
        <ul>
          <li><a href="/">Home</a></li>
          <li><a href="/world">World</a></li>
          <li><a href="/tech">Tech</a></li>
        </ul>
      </nav>
    
      <main id="content">
        <h2>Top Story</h2>
        <p>Today’s lead article goes here.</p>
    
        <iframe title="Sponsored video" src="/widgets/video.html"></iframe>
      </main>
    
      <aside aria-label="Related links">
        <ul>
          <li><a href="#">More headlines</a></li>
        </ul>
      </aside>
    
      <footer>
        <p>© 2026 Acme News</p>
      </footer>
    </body>
    </html>
    
    Contents of widgetsvideo.html (iframe document with no main because it’s just a player):
    HTML
    !doctype html>
    <html lang="en">
    <head><meta charset="utf-8"><title>Video Player</title></head>
    <body>
      <div role="application" aria-label="Video player">
        <button aria-label="Play"></button>
      </div>
    </body>
    </html>

    Bad Example

    HTML
    !doctype html>
    <html lang="en">
    <head><meta charset="utf-8"><title>Bad Landmarks</title></head>
    <body>
      <header><h1>Shop</h1></header>
    
      <div role="main">
        <h2>Featured Products</h2>
      </div>
    
      <main>
        <p>Duplicate primary content area appears here.</p>
        <iframe title="Promo" src="/promo.html"></iframe>
      </main>
    
      <footer><p>© 2026</p></footer>
    </body>
    </html>
    
    Contents of promo.html (iframe document with two mains – also incorrect):
    HTML
    !doctype html>
    <html lang="en">
    <head><meta charset="utf-8"><title>Promo</title></head>
    <body>
      <main>
        <h2>Deal of the Day</h2>
      </main>
      <div role="main">
        <p>Second main region (should be removed).</p>
      </div>
    </body>
    </html>

    Quick Checklist

    • Exactly one <main> or role="main" per document; never both or more.
    • Do not nest main inside article, aside, header, footer, nav, or another main.
    • Keep header, nav, and footer outside of main.
    • Use native landmarks; add ARIA roles only when no suitable element exists.
    • Label repeated nav/aside/region landmarks with aria-label.
    • Iframes: zero or one main depending on whether they host primary content; always add a meaningful title.
    • SPAs: maintain one persistent main and update its content.
    • Validate with a screen reader’s landmarks list and confirm counts for the page and each iframe.