The <main> element wraps the primary content of a page — the unique content that distinguishes this page from every other page on the site. It is a landmark that screen readers, search engines, and AI crawlers use to skip directly to "the actual content," past navigation, banners, and sidebars. Every page should have exactly one.
<main> is one of the two recognized techniques (the other is a skip link).landmark-one-main rule: every page must contain exactly one <main> (or one element with role="main"). Zero is a failure. More than one is a failure.<main> is one of the most common automated-audit failures — present on roughly 26% of the top one million home pages (WebAIM Million 2024).Think of <main>the way you think of the table of contents in a book pointing at "Chapter 1." Without it, a screen-reader user has to listen to the cover, the dedication, the foreword, and the publisher's notes every single time they open a new page.
<main>. Without it, every visit forces them to tab through navigation, ads, and banners before reaching the content.<main> as a valid way to skip repeated blocks. It is the cleanest way to satisfy a Level A criterion.<main> boundary to separate primary content from boilerplate (header, nav, footer). This influences how snippets and AI Overview citations are extracted from the page.<main> boundary directly affects which paragraphs are extracted as a citation versus discarded as chrome.The HTML5 specification is precise: a document should have exactly one <main>, and its content must be the page's dominant content. It must not be a descendant of <article>, <aside>, <header>, <nav>, or <footer>.
What goes inside <main>: the page's unique content — the article, the product detail, the form, the search results.
What does NOT go inside <main>: site-wide navigation, the global header, the footer, the cookie banner, the language switcher, or sidebars that repeat across pages.
<!-- Bad: no <main> at all -->
<body>
<header>...</header>
<nav>...</nav>
<div class="content">
<h1>Article title</h1>
<p>...</p>
</div>
<footer>...</footer>
</body>
<!-- Bad: multiple <main> elements (audit failure) -->
<body>
<main>...</main>
<main>...</main>
</body>
<!-- Bad: <main> wrapping the entire page chrome -->
<body>
<main>
<header>...</header>
<nav>...</nav>
<article>...</article>
<footer>...</footer>
</main>
</body>
<!-- Good: single <main>, chrome outside, skip-link target -->
<body>
<a href="#main-content" class="skip-link">
Skip to main content
</a>
<header>
<nav aria-label="Primary">...</nav>
</header>
<main id="main-content">
<h1>Article title</h1>
<p>The unique content of this page lives here.</p>
</main>
<footer>...</footer>
</body><main> or containing more than one, and pairs each issue with an AI-generated fix or one-click GitHub PR.<main> landmark across every indexable page, so you can see which templates (product, article, listing) are missing it.<main> boundary.axe-core — runs the landmark-one-main rule against any page in CI; a one-line failure when zero or more than one <main> is present.The HTML5 specification and the landmark-one-main rule both require it. If a page renders zero or two, screen-reader navigation breaks and automated audits fail.
Both work, but <main> is shorter, communicates intent in the markup, and is impossible to misspell. Reach for role="main" only when you cannot change the tag (legacy CMS templates).
Keep <main> as a direct child of <body>, sitting beside <header>, <nav>, and <footer>. Nesting it inside any of those is invalid HTML.
Add <a href="#main-content">Skip to main content</a> as the first focusable element on the page and give <main> the matching id. Sighted keyboard users get the same shortcut screen-reader users already have.
Add tabindex="-1" on <main> so that following a skip link reliably moves keyboard focus there. Without it, some browsers move only the scroll position.
<main id="main-content" tabindex="-1">
<h1>Page title</h1>
...
</main>The page's primary heading belongs to its primary content. This pairs the H1 with the mainlandmark in the accessibility tree, helping AI engines extract a clean "title + body" pair when they cite your page.
Logos, primary navigation, search forms shared across pages, language switchers, cookie banners, and the global footer go outside <main>. Including them defeats the purpose of having a primary-content landmark.
Single-page apps that swap views via client routing sometimes leave a stale <main> in the DOM and append a new one — producing two simultaneous mains. After every route change, verify that exactly one <main> is present.
What's happening: the template wraps content in <div class="content"> instead of <main>. Screen-reader users have no shortcut to the article; the landmark-one-main rule fails.
Fix: change the wrapping <div> to <main id="main-content">. No CSS changes are required — <main> is a block element with the same default rendering as <div>.
What's happening: a layout component renders one <main>, and a nested page component renders another. Both are visible in the DOM.
Fix: own the <main> at exactly one layer of the layout. If a child needs a primary-content wrapper, give it a different element (such as <article>) and keep <main> reserved for the outermost layout.
What's happening: a developer wrapped the entire body in <main> to satisfy an audit warning, defeating the purpose. Screen-reader users now jump to <main> only to land on the site logo.
Fix: move <header>, <nav>, and <footer> outside <main>, leaving only the page-specific content inside.
What's happening: the previous route's <main> is still in the DOM when the new route mounts its own. The page now has two.
Fix: ensure the layout component renders one persistent <main> across route changes, and that route content renders inside it as children — not as a sibling that brings its own <main>.
<main> is one of several landmark elements introduced in HTML5. Each plays a distinct role in the accessibility tree.
| Element | Implicit ARIA Role | Per-Page Limit | Purpose |
|---|---|---|---|
<main> | main | Exactly one | The page's unique primary content. |
<header> (top-level) | banner | One per page (when at body level) | Site-wide branding, logo, primary nav container. |
<nav> | navigation | Multiple allowed (label each) | Major navigation blocks (primary, footer, breadcrumbs). |
<aside> | complementary | Multiple allowed | Sidebars, related content, callouts. |
<footer> (top-level) | contentinfo | One per page (when at body level) | Site-wide footer: copyright, secondary links. |
<article> | article | Multiple allowed | Self-contained content (a single post in a feed). |
WCAG does not literally require the <main> tag, but it requires that users be able to programmatically determine page structure (SC 1.3.1) and bypass repeated blocks (SC 2.4.1). The <main> landmark is the cleanest way to satisfy both at Level A. The landmark-one-main automated rule fails any page that has zero or more than one.
No. The HTML5 specification permits multiple <main> elements only when all but one have hidden applied. In practice, treat the rule as "exactly one visible <main> per page" — every accessibility audit, including landmark-one-main, treats two as a failure.
Prefer the native <main> element. It is shorter, easier to read, and harder to misspell than <div role="main">. The first rule of ARIA is "use a native element when one exists." Reach for role="main" only when the markup cannot be changed.
A site-wide search form belongs in the header, outside <main>. A search results page's search field and results list are the page's primary content and belong inside <main>. Breadcrumbs are situational — many sites place them inside <main>as part of the page's context; either pattern is acceptable as long as it stays consistent.
For screen-reader users who navigate by landmarks, yes — they can jump straight to <main>. But sighted keyboard users do not have landmark shortcuts, so a visible skip link pointing at #main-content still matters. The two work best together.
Generative engines parse the accessibility tree to separate primary content from chrome. A page with a clear <main> boundary lets them extract clean "article body" passages for citation; a page wrapped in nested <div>s forces them to guess where the content begins, often pulling in nav and footer text or skipping the page entirely.
Any unique id works, but pick a stable convention — main-content and main are both common — and reuse it across the site so a single skip link template can target it everywhere. Add tabindex="-1" so following the skip link reliably moves keyboard focus.
The <main> landmark is one of the cheapest accessibility wins available: a single tag, no CSS changes, and it satisfies two Level A WCAG criteria while improving SEO and AI citation quality at the same time. The rule is simple — exactly one <main>per page, holding only the page's unique content, with the global header, nav, and footer as siblings outside it.
Run a Greadme deep scan to see every page that's missing <main> (or has more than one), and fix them in order of traffic.