HTML Guides for main
Learn how to identify and fix common HTML validation errors flagged by the W3C Validator — so your pages are standards-compliant and render correctly across every browser. Also check our Accessibility Guides.
The <main> element represents the dominant, unique content of a document — the primary content that is directly related to or expands upon the central topic of the page. Having more than one visible <main> element creates ambiguity: browsers, screen readers, and other assistive technologies use <main> to identify the primary content area, and multiple visible instances make it unclear which content block is truly the main one.
This is particularly important for accessibility. Screen reader users often rely on landmark navigation to jump directly to the main content of a page. When multiple visible <main> elements exist, this shortcut becomes unreliable or confusing, as the user has no way to know which <main> holds the content they’re looking for.
There are legitimate scenarios where multiple <main> elements make sense — for example, in single-page applications (SPAs) where different views are swapped in and out dynamically using JavaScript. The HTML specification accommodates this by allowing multiple <main> elements as long as only one is visible at a time. The others must be hidden using the hidden attribute.
How to fix it
- If you only need one main content area, remove the extra <main> elements and keep just one.
- If you need multiple views (e.g., for tabbed content or SPA-style navigation), add the hidden attribute to all <main> elements except the one currently active. Use JavaScript to toggle visibility by adding or removing the hidden attribute as needed.
Examples
❌ Invalid: Two visible <main> elements
<header>
<h1>My Website</h1>
</header>
<main>
<h2>Welcome</h2>
<p>This is the home page content.</p>
</main>
<main>
<h2>About</h2>
<p>This is the about page content.</p>
</main>
Both <main> elements are visible, which violates the specification and confuses assistive technologies.
✅ Fixed: Single <main> element
If you don’t need multiple views, simply use one <main>:
<header>
<h1>My Website</h1>
</header>
<main>
<h2>Welcome</h2>
<p>This is the home page content.</p>
</main>
✅ Fixed: Multiple <main> elements with only one visible
If you need multiple views for JavaScript-driven navigation, hide all but the active one using the hidden attribute:
<header>
<nav>
<button onclick="switchView('home')">Home</button>
<button onclick="switchView('about')">About</button>
</nav>
</header>
<main id="home">
<h2>Welcome</h2>
<p>This is the home page content.</p>
</main>
<main id="about" hidden>
<h2>About</h2>
<p>This is the about page content.</p>
</main>
In this pattern, JavaScript would toggle the hidden attribute when the user navigates between views, ensuring only one <main> is ever visible at a time.
❌ Invalid: Using CSS instead of hidden
Note that hiding a <main> element with CSS (e.g., display: none or visibility: hidden) does not satisfy the HTML specification. The validator checks for the hidden attribute, not CSS styles:
<!-- This still triggers the validation error -->
<main>
<h2>Welcome</h2>
</main>
<main style="display: none;">
<h2>About</h2>
</main>
Always use the hidden attribute to indicate that a <main> element is not currently relevant to the page.
A main element cannot be placed inside an article element according to HTML5 content model rules.
The main element is intended to identify the dominant content of the <body> that is directly related to, or expands upon, the central topic of a document. It is meant to be unique, appearing only once per document, and must not be a descendant of elements like article, aside, header, footer, or nav. Conversely, the article element represents a self-contained composition that could independently be reused or distributed, such as a blog post or news story.
To resolve the error, move the main element so that it is a direct child of the body, and place any article elements inside the main or at the same level, not the other way around.
Incorrect:
<article>
<main>
<h1>Article Title</h1>
<p>This is the article content.</p>
</main>
</article>
Correct:
<main>
<article>
<h1>Article Title</h1>
<p>This is the article content.</p>
</article>
</main>
Minimal valid HTML document:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Article in Main Example</title>
</head>
<body>
<main>
<article>
<h1>Article Title</h1>
<p>This is the article content.</p>
</article>
</main>
</body>
</html>
Use only one main element per page and ensure it is not nested inside sectioning elements such as article.
The <main> element identifies the primary content of a page — the content that is directly related to or expands upon the central topic of the document. According to the WHATWG HTML living standard, a <main> element must not appear as a descendant of another <main> element. This rule exists because the semantic purpose of <main> is to mark a single, unique content region; nesting it creates a contradictory structure where one “primary content area” exists inside another.
This matters for several important reasons:
- Accessibility: Screen readers and other assistive technologies use the <main> landmark to allow users to skip directly to the primary content. When multiple or nested <main> elements exist, this navigation breaks down — assistive technology may only recognize one of them, or it may present a confusing hierarchy of “main” landmarks to the user.
- Standards compliance: Browsers and validators enforce the HTML specification’s content model for <main>. A nested <main> violates that content model and produces a validation error.
- Semantic clarity: The <main> element carries specific meaning. Nesting it dilutes that meaning and signals a structural misunderstanding of the document to both machines and other developers.
This issue commonly arises when composing pages from multiple templates or components — for example, when a layout template already wraps content in <main> and an inner component or partial also includes its own <main> element. It can also happen during refactoring when code is moved between files without checking the surrounding structure.
To fix the issue, identify the nested <main> element and replace it with a more appropriate element. If the inner content represents a thematic grouping, use <section>. If it represents a self-contained composition (like a blog post or comment), use <article>. If no particular semantic meaning is needed, a plain <div> works fine.
Examples
❌ Invalid: nested <main> elements
<main>
<h1>Welcome</h1>
<main>
<p>This nested main element is invalid.</p>
</main>
</main>
The inner <main> is a descendant of the outer <main>, which violates the content model.
✅ Fixed: inner <main> replaced with <section>
<main>
<h1>Welcome</h1>
<section>
<h2>Introduction</h2>
<p>This section is valid inside main.</p>
</section>
</main>
❌ Invalid: deeply nested <main> inside other elements
The nesting doesn’t have to be direct. A <main> anywhere inside another <main> triggers this error:
<main>
<h1>Dashboard</h1>
<div class="content-wrapper">
<article>
<main>
<p>Still invalid, even though it's nested several levels deep.</p>
</main>
</article>
</div>
</main>
✅ Fixed: replaced with <div>
<main>
<h1>Dashboard</h1>
<div class="content-wrapper">
<article>
<div>
<p>Now valid with a neutral container element.</p>
</div>
</article>
</div>
</main>
❌ Invalid: component templates each providing <main>
This pattern often appears in frameworks where a layout and a page component both define <main>:
<!-- Layout template wraps page content -->
<main>
<!-- Page component output -->
<main>
<h1>About Us</h1>
<p>Our story begins...</p>
</main>
</main>
✅ Fixed: <main> only in the layout
<!-- Layout template wraps page content -->
<main>
<!-- Page component output -->
<h1>About Us</h1>
<p>Our story begins...</p>
</main>
Keep <main> at whichever level makes the most sense for your architecture — typically the outermost layout — and remove it from inner components. If you need to group the inner content, use <section>, <article>, or <div> instead.
The <main> element serves a specific structural role: it identifies the primary content of the page, distinct from repeated elements like headers, footers, and navigation. Because of this unique purpose, the HTML specification strictly limits where <main> can appear in the document tree. Nesting <main> inside a <section> element violates these rules because <section> represents a thematic grouping of content — placing <main> inside it implies that the dominant page content is merely a subsection of something else, which is semantically contradictory.
According to the WHATWG HTML living standard, a hierarchically correct <main> element is one whose ancestor elements are limited to <html>, <body>, <div>, <form> (without an accessible name), and autonomous custom elements. This means <main> cannot be a descendant of <article>, <aside>, <footer>, <header>, <nav>, or <section>.
Why this matters
- Accessibility: Screen readers and assistive technologies use the <main> element as a landmark to let users skip directly to the primary content. When <main> is incorrectly nested inside <section>, assistive technologies may misinterpret the document structure, making navigation harder for users who rely on landmarks.
- Standards compliance: Browsers are lenient and will render the page regardless, but the semantic meaning is broken. Future browser features or tools that depend on correct document structure may not work as expected.
- Document structure clarity: The <main> element should clearly sit at the top level of your content hierarchy, making it immediately obvious to both developers and machines which part of the page is the primary content.
Additional rules for <main>
Beyond the ancestor restriction, remember that a document must not have more than one visible <main> element. If you use multiple <main> elements (for example, in a single-page application), all but one must have the hidden attribute specified.
Examples
Incorrect: <main> nested inside <section>
This structure places <main> as a descendant of <section>, which triggers the validation error:
<body>
<header>
<h1>My Website</h1>
</header>
<section>
<main>
<h2>Welcome</h2>
<p>This is the primary content of the page.</p>
</main>
</section>
</body>
Correct: <main> as a sibling of <section>
Move <main> out of the <section> so it is a direct child of <body>:
<body>
<header>
<h1>My Website</h1>
</header>
<main>
<h2>Welcome</h2>
<p>This is the primary content of the page.</p>
</main>
<section>
<h2>Related Topics</h2>
<p>Additional thematic content goes here.</p>
</section>
</body>
Correct: <section> elements inside <main>
If your primary content is divided into thematic sections, nest the <section> elements inside <main> — not the other way around:
<body>
<header>
<h1>My Website</h1>
</header>
<main>
<section>
<h2>Introduction</h2>
<p>An overview of the topic.</p>
</section>
<section>
<h2>Details</h2>
<p>A deeper dive into the subject.</p>
</section>
</main>
<footer>
<p>© 2024 My Website</p>
</footer>
</body>
Correct: <main> wrapped in a <div>
If your layout requires a wrapper element around <main>, a <div> is a valid ancestor:
<body>
<div class="layout-wrapper">
<header>
<h1>My Website</h1>
</header>
<main>
<h2>Welcome</h2>
<p>This is the primary content of the page.</p>
</main>
</div>
</body>
The key principle is simple: <main> defines the dominant content of the entire document, so it belongs at the top level of your content hierarchy. Sectioning elements like <section>, <article>, <aside>, <nav>, <header>, and <footer> should never wrap <main> — instead, they should be placed as children or siblings of it.
The ARIA specification defines a set of roles that convey the purpose of an element to assistive technologies like screen readers. Many HTML elements have implicit ARIA roles — built-in semantics that map directly to ARIA roles without any extra markup. The <main> element is one of these: it automatically communicates the main landmark role to assistive technologies.
When you write <main role="main">, you’re explicitly stating something the browser and assistive technologies already know. The W3C validator warns about this redundancy because it can signal a misunderstanding of how native HTML semantics work. While it won’t break anything, unnecessary attributes add noise to your markup and can make code harder to maintain.
This principle applies broadly across HTML. For example, <nav> implicitly has role="navigation", <header> implicitly has role="banner" (when not nested inside a sectioning element), and <button> implicitly has role="button". Explicitly restating these roles is discouraged by both the W3C and the ARIA in HTML specification, which states: “Setting an ARIA role and/or `aria-` attribute that matches the implicit ARIA semantics is unnecessary and is NOT RECOMMENDED.”*
Why this matters
- Code clarity: Redundant attributes make your HTML harder to read and can confuse other developers into thinking the attribute is necessary.
- Standards compliance: The W3C validator raises a warning, which can obscure more important issues in your validation reports.
- Best practices: Following the principle of using native HTML semantics without redundant ARIA keeps your code clean and aligns with the first rule of ARIA: “If you can use a native HTML element with the semantics and behavior you require already built in, do so, instead of re-purposing an element and adding an ARIA role.”
How to fix it
Remove the role="main" attribute from any <main> element. The semantic meaning is already provided by the element itself.
If you’re working with a <div> or another generic element that needs the main landmark role (for example, in a legacy codebase that cannot use <main>), then role="main" is appropriate and necessary on that element.
Examples
❌ Redundant role on <main>
<main role="main">
<h1>Welcome to my site</h1>
<p>This is the primary content of the page.</p>
</main>
The role="main" attribute is unnecessary here because <main> already implies it.
✅ Using <main> without a redundant role
<main>
<h1>Welcome to my site</h1>
<p>This is the primary content of the page.</p>
</main>
✅ Using role="main" on a non-semantic element (when necessary)
<div role="main">
<h1>Welcome to my site</h1>
<p>This is the primary content of the page.</p>
</div>
This approach is valid when you cannot use the <main> element — for instance, due to framework constraints or legacy browser support requirements. In most modern projects, prefer the <main> element instead.
Ready to validate your sites?
Start your free trial today.