HTML Guides for section
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 W3C HTML validator enforces rules about which ARIA roles can be applied to specific HTML elements. The <section> element carries implicit semantics — it maps to the ARIA region role when it has an accessible name (e.g., via aria-label or aria-labelledby). While article is indeed a valid ARIA role defined in the WAI-ARIA specification, the HTML specification restricts which roles can override a <section> element’s native semantics. The allowed roles for <section> include alert, alertdialog, application, contentinfo, dialog, document, feed, log, main, marquee, navigation, none, note, presentation, search, status, tabpanel, and region — but not article.
This restriction exists because HTML already provides the <article> element, which carries the implicit article ARIA role natively. Using role="article" on a <section> creates a confusing mismatch: the element’s tag name suggests one semantic meaning while the role attribute declares another. This can confuse assistive technologies like screen readers, which may announce the element inconsistently depending on whether they prioritize the tag name or the explicit role.
The best fix depends on your intent:
- If the content is self-contained and independently meaningful (like a blog post, comment, or news story), replace the <section> with an <article> element. The <article> element already has the implicit article role, so no role attribute is needed.
- If the content is a thematic grouping within a page, keep the <section> element and remove the role attribute. Give it a heading or an aria-label so it functions as a meaningful landmark.
- If you specifically need the article role on a non-semantic element, use a <div> with role="article" instead, since <div> has no implicit role and allows any ARIA role to be applied.
Examples
Incorrect: role="article" on a <section>
This triggers the validation error because article is not a permitted role for <section>.
<section role="article">
<h2>Breaking news</h2>
<p>Details about the event.</p>
</section>
Correct: use <article> for self-contained content
The <article> element has the implicit article role, making the explicit role attribute unnecessary.
<article>
<h2>Breaking news</h2>
<p>Details about the event.</p>
</article>
Correct: use <section> without a conflicting role
If the content is a thematic grouping rather than a standalone piece, keep <section> and drop the role attribute. Adding an accessible name via aria-labelledby makes it a region landmark.
<section aria-labelledby="news-heading">
<h2 id="news-heading">Latest news</h2>
<p>Details about the event.</p>
</section>
Correct: use a <div> when you need an explicit article role
In rare cases where you cannot use the <article> element but need the article role, a <div> accepts any valid ARIA role.
<div role="article">
<h2>Breaking news</h2>
<p>Details about the event.</p>
</div>
Correct: nest <article> inside <section> for grouped articles
If you need both a thematic grouping and individual self-contained items, nest <article> elements inside a <section>.
<section aria-labelledby="stories-heading">
<h2 id="stories-heading">Top stories</h2>
<article>
<h3>First story</h3>
<p>Story content.</p>
</article>
<article>
<h3>Second story</h3>
<p>Story content.</p>
</article>
</section>
As a general rule, prefer native HTML elements over ARIA roles whenever possible. The <article> element communicates the article role more reliably than any ARIA override, and it works consistently across all browsers and assistive technologies without additional attributes.
The section element carries implicit ARIA semantics — it maps to role="region" when given an accessible name. According to the ARIA in HTML specification, each HTML element has a set of roles it is allowed to assume, and list is not among the permitted roles for section. When the W3C validator encounters role="list" on a section, it flags this as a bad value because the role conflicts with the element’s intended purpose as a sectioning landmark.
This matters for several reasons. First, assistive technologies like screen readers rely on the correct pairing of elements and roles to convey page structure. A section announced as a list creates a confusing, contradictory experience — the underlying DOM says “this is a document section” while the ARIA role says “this is a list.” Second, browsers may handle conflicting semantics unpredictably, leading to inconsistent behavior across platforms. Third, the HTML specification explicitly defines which roles are valid on each element, and violating these rules means your markup is non-conforming.
The best fix is almost always to use native HTML list elements. The ul, ol, and li elements provide built-in list semantics that all browsers and assistive technologies understand without any extra ARIA attributes. Native elements also handle keyboard interaction and focus management correctly out of the box.
If your design requires a custom component where native list markup isn’t feasible — for example, a complex card grid that functions as a list — you can apply role="list" to a semantically neutral element like div or span. Each direct child acting as a list item should then receive role="listitem". This approach satisfies the ARIA specification while avoiding the element-role conflict.
If you actually need a section to group content within a page region and the list is just part of that section, nest a proper list inside the section rather than trying to make the section itself behave as a list.
Examples
❌ Bad: role="list" on a section element
This triggers the validation error because list is not an allowed role for section.
<section role="list">
<div>Item A</div>
<div>Item B</div>
</section>
✅ Fixed: Use native list elements (recommended)
Native lists provide the best accessibility support with no ARIA needed.
<ul>
<li>Item A</li>
<li>Item B</li>
</ul>
✅ Fixed: Nest a list inside the section
If you need the sectioning semantics of section alongside a list, nest the list inside it.
<section aria-labelledby="resources-heading">
<h2 id="resources-heading">Resources</h2>
<ul>
<li>Item A</li>
<li>Item B</li>
</ul>
</section>
✅ Fixed: ARIA roles on a neutral container
Use this only when native list markup is not possible, such as for highly custom UI components.
<div role="list">
<div role="listitem">Item A</div>
<div role="listitem">Item B</div>
</div>
✅ Fixed: Remove the role entirely
If the content isn’t actually a list, simply remove the role attribute and let the section carry its natural semantics.
<section>
<h2>Updates</h2>
<div>Item A</div>
<div>Item B</div>
</section>
The value section does not exist in the WAI-ARIA specification. ARIA defines a specific set of role values, and section is not among them. This is likely a confusion between the HTML element name <section> and the ARIA role region, which is the role that the <section> element implicitly maps to. Because section is not a recognized role, the validator rejects it as an invalid value.
This matters for several reasons. First, assistive technologies like screen readers rely on ARIA roles to communicate the purpose of elements to users. An unrecognized role value may be ignored entirely or cause unexpected behavior, degrading the experience for users who depend on these tools. Second, the <section> element already carries native semantics equivalent to role="region" (when it has an accessible name), so adding a redundant or incorrect role provides no benefit and introduces potential problems.
According to the ARIA in HTML specification, you should generally avoid setting a role on elements that already have appropriate native semantics. The <section> element’s implicit role is region, so explicitly adding role="region" is redundant in most cases. The simplest and best fix is to remove the role attribute altogether and let the native HTML semantics do their job.
If you do need to override an element’s role for a specific design pattern (for example, turning a <section> into a navigation landmark), use a valid ARIA role from the WAI-ARIA specification.
Examples
Incorrect: using the invalid section role
<section role="section">
<h2>About Us</h2>
<p>Learn more about our team.</p>
</section>
This triggers the validation error because section is not a valid ARIA role value.
Correct: remove the role attribute
<section>
<h2>About Us</h2>
<p>Learn more about our team.</p>
</section>
The <section> element already provides the correct semantics. No role attribute is needed.
Correct: use a valid ARIA role if needed
If you have a specific reason to assign a role, use a valid one. For example, if a <section> is being used as a navigation landmark:
<section role="navigation" aria-label="Main navigation">
<ul>
<li><a href="/">Home</a></li>
<li><a href="/about">About</a></li>
</ul>
</section>
In practice, you would typically use a <nav> element instead, which has the navigation role natively. This example simply illustrates that if you do apply a role, it must be a valid ARIA role value.
Correct: explicit region role with an accessible name
If you want to explicitly mark a section as a named region landmark, you can use role="region" along with an accessible name. However, this is redundant when using <section> with an aria-label or aria-labelledby, since the browser already maps it to region:
<!-- Preferred: native semantics handle the role -->
<section aria-labelledby="features-heading">
<h2 id="features-heading">Features</h2>
<p>Explore our product features.</p>
</section>
<!-- Also valid but redundant -->
<section role="region" aria-labelledby="features-heading">
<h2 id="features-heading">Features</h2>
<p>Explore our product features.</p>
</section>
Both are valid HTML, but the first approach is cleaner and follows the principle of relying on native semantics whenever possible.
The <section> element defines a standalone thematic grouping within a document — think chapters, tabbed panels, or distinct parts of a page like “About Us” or “Contact.” According to the HTML specification, each <section> should generally include a heading that identifies its content. When a <section> lacks a heading, the validator raises this warning because the element isn’t being used as intended.
This matters for several reasons:
Accessibility. Screen readers and other assistive technologies use headings to build an outline of the page. When a user navigates by sections, the heading is what identifies each one. A <section> without a heading appears as an “untitled section” in the document outline, which makes it difficult or impossible for assistive technology users to understand the page structure or jump to the content they need.
Semantics. The whole purpose of <section> is to group related content under a common theme, and that theme should be labeled with a heading. If your content doesn’t need a heading, it may not be a true “section” in the semantic sense, and a <div> (which carries no semantic meaning) might be a better fit.
Document outline. Browsers and tools that generate document outlines rely on headings within sectioning elements. Missing headings create gaps in the outline, reducing the usefulness of the page structure.
How to fix it
You have three main options:
-
Add a heading — Place an <h2>–<h6> element at the beginning of the <section>. This is the preferred solution when the section genuinely represents a thematic block of content.
-
Use aria-label or aria-labelledby — If a visible heading doesn’t suit your design, you can label the section for assistive technologies using an ARIA attribute. This resolves the accessibility concern, though the validator may still show the warning.
-
Switch to <div> — If the content doesn’t represent a meaningful, identifiable section of the document, replace <section> with a <div>. There’s no expectation for a <div> to have a heading.
Examples
❌ Section without a heading
This triggers the warning because neither <section> has a heading:
<h1>All about guitars</h1>
<section>
<p>Acoustic, electric, classical... we have them all!</p>
</section>
<section>
<p>Analog, digital, portable...</p>
</section>
✅ Fixed: Adding headings to each section
<h1>All about guitars</h1>
<section>
<h2>Guitar types</h2>
<p>Acoustic, electric, classical... we have them all!</p>
</section>
<section>
<h2>Amplifiers</h2>
<p>Analog, digital, portable...</p>
</section>
✅ Fixed: Using aria-label when a visible heading isn’t appropriate
<section aria-label="Guitar types">
<p>Acoustic, electric, classical... we have them all!</p>
</section>
✅ Fixed: Using aria-labelledby to reference an existing element
<section aria-labelledby="guitar-heading">
<span id="guitar-heading" class="visually-hidden">Guitar types</span>
<p>Acoustic, electric, classical... we have them all!</p>
</section>
✅ Fixed: Replacing with <div> when no section semantics are needed
If you’re only using the element as a styling wrapper and the content doesn’t form a distinct thematic group, use a <div> instead:
<h1>All about guitars</h1>
<div class="content-block">
<p>Acoustic, electric, classical... we have them all!</p>
</div>
<div class="content-block">
<p>Analog, digital, portable...</p>
</div>
As a general rule, reach for <section> when your content has a clear topic that deserves a heading, and use <div> when you need a generic container for layout or styling purposes.
The word “stray” in this error message means the validator encountered a start tag in a place where no element of that kind is allowed according to the HTML specification. The <section> element is flow content, so it must appear inside the <body> element (or inside another element that accepts flow content, such as <main>, <article>, <div>, etc.). When the validator sees <section> somewhere it can’t legally exist, it flags it as “stray.”
There are several common causes for this error:
- Content placed after </body> or </html>: The most frequent cause. Extra markup exists beyond the closing tags of the document body.
- Premature closing of the <body>: An extra or misplaced </body> tag earlier in the document causes the browser to consider the body closed, making any subsequent <section> stray.
- Nesting inside elements that don’t accept flow content: Placing <section> directly inside a <p>, <span>, <a>, or other phrasing-content-only element. Since these elements can’t contain block-level flow content, the browser implicitly closes the parent, leaving <section> in an invalid position.
- Malformed or unclosed tags: Earlier syntax errors — like a missing closing > on a tag — can shift the parser’s understanding of the document tree, causing downstream elements to appear stray.
This matters because browsers use error recovery when they encounter stray elements, and different browsers may handle the recovery differently. Your content could end up outside the visible document, be rendered inconsistently, or cause accessibility tools to misinterpret the page structure. Fixing this error ensures predictable rendering and a well-formed document.
Examples
Stray <section> after the closing </body> tag
This is the most common scenario. Content placed after </body> has nowhere valid to go:
<!-- ❌ Incorrect: section appears after </body> -->
<!DOCTYPE html>
<html lang="en">
<head>
<title>Example</title>
</head>
<body>
<h1>Welcome</h1>
<p>Some content.</p>
</body>
<section>
<h2>About</h2>
<p>This section is stray.</p>
</section>
</html>
Move the <section> inside the <body>:
<!-- ✅ Correct: section is inside <body> -->
<!DOCTYPE html>
<html lang="en">
<head>
<title>Example</title>
</head>
<body>
<h1>Welcome</h1>
<p>Some content.</p>
<section>
<h2>About</h2>
<p>This section is properly placed.</p>
</section>
</body>
</html>
Extra </body> tag causing a premature close
A duplicate closing tag can trick the parser into ending the body early:
<!-- ❌ Incorrect: extra </body> causes section to become stray -->
<!DOCTYPE html>
<html lang="en">
<head>
<title>Example</title>
</head>
<body>
<div>
<p>Main content.</p>
<!-- accidental extra closing tag -->
</div>
<section>
<h2>Updates</h2>
<p>This is now stray.</p>
</section>
</body>
</html>
Remove the extra </body> tag:
<!-- ✅ Correct: single </body> at the end -->
<!DOCTYPE html>
<html lang="en">
<head>
<title>Example</title>
</head>
<body>
<div>
<p>Main content.</p>
</div>
<section>
<h2>Updates</h2>
<p>This is correctly placed now.</p>
</section>
</body>
</html>
Nesting <section> inside a <p> element
The <p> element only accepts phrasing content. When the parser encounters a <section> inside a <p>, it implicitly closes the <p> first, which can leave the <section> in an unexpected position:
<!-- ❌ Incorrect: section nested inside a paragraph -->
<p>
Introduction text.
<section>
<h2>Details</h2>
<p>More info here.</p>
</section>
</p>
Separate the paragraph and section into siblings:
<!-- ✅ Correct: section is a sibling, not a child of <p> -->
<p>Introduction text.</p>
<section>
<h2>Details</h2>
<p>More info here.</p>
</section>
Unclosed tag causing downstream errors
A missing closing angle bracket on an earlier element can corrupt the parser’s view of the entire document tree:
<!-- ❌ Incorrect: missing > on the </div causes parsing issues -->
<body>
<div>
<p>Content here.</p>
</div
<section>
<h2>Topics</h2>
<p>This may be flagged as stray.</p>
</section>
</body>
Fix the malformed tag:
<!-- ✅ Correct: properly closed </div> -->
<body>
<div>
<p>Content here.</p>
</div>
<section>
<h2>Topics</h2>
<p>No longer stray.</p>
</section>
</body>
How to debug this issue
- Check the line number reported by the validator and look at what comes before the <section> tag — the problem is usually above it, not at the <section> itself.
- Search for extra closing tags like </body>, </html>, or </div> that might prematurely close a container.
- Verify parent elements — make sure <section> isn’t nested inside <p>, <span>, <a>, <button>, or other elements that only accept phrasing content.
- Use proper indentation to make the document hierarchy visually clear. Misplaced tags are much easier to spot in well-formatted code.
- Revalidate after each fix, since correcting one stray tag error often resolves multiple related warnings.
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 HTML specification and WAI-ARIA guidelines establish that certain HTML elements carry implicit landmark roles. The <section> element implicitly maps to role="region", meaning assistive technologies like screen readers already recognize it as a region landmark without any additional ARIA markup. This principle is captured by the first rule of ARIA use: “If you can use a native HTML element or attribute with the semantics and behavior you require already built in, instead of re-purposing an element and adding an ARIA role, state or property to make it accessible, then do so.”
Adding role="region" to a <section> doesn’t change the element’s behavior or how assistive technologies interpret it — it simply duplicates what the browser already communicates. The W3C Validator warns about this redundancy to encourage cleaner, more maintainable markup and to help developers understand native HTML semantics.
This same principle applies to other HTML elements with implicit roles: <nav> has an implicit role="navigation", <main> has role="main", <aside> has role="complementary", <header> has role="banner" (when not nested in a sectioning element), and <footer> has role="contentinfo" (when not nested in a sectioning element). Adding these explicit roles to their corresponding elements will trigger similar validator warnings.
It’s worth noting that a <section> element is only exposed as a region landmark by assistive technologies when it has an accessible name. If your <section> doesn’t have an accessible name (via aria-label, aria-labelledby, or similar mechanisms), screen readers may not treat it as a navigable landmark — but this still doesn’t mean you should add role="region", since the implicit role mapping remains the same regardless.
How to fix it
- Remove the role="region" attribute from any <section> element.
- If you want the section to be a meaningful landmark for screen reader users, give it an accessible name using aria-labelledby (pointing to a heading) or aria-label.
- Never add explicit ARIA roles that duplicate the implicit role of a native HTML element.
Examples
Incorrect: redundant role on section
<section role="region">
<h2>Contact Information</h2>
<p>Email us at info@example.com</p>
</section>
Correct: section without redundant role
<section>
<h2>Contact Information</h2>
<p>Email us at info@example.com</p>
</section>
Correct: section with an accessible name for landmark navigation
Using aria-labelledby to associate the section with its heading ensures assistive technologies expose it as a named landmark region:
<section aria-labelledby="contact-heading">
<h2 id="contact-heading">Contact Information</h2>
<p>Email us at info@example.com</p>
</section>
Correct: section with aria-label when no visible heading exists
<section aria-label="Contact information">
<p>Email us at info@example.com</p>
</section>
Incorrect: redundant roles on other landmark elements
The same principle applies to other native landmark elements. Avoid these patterns:
<nav role="navigation">
<a href="/">Home</a>
</nav>
<main role="main">
<p>Page content</p>
</main>
<aside role="complementary">
<p>Related links</p>
</aside>
Correct: landmark elements without redundant roles
<nav>
<a href="/">Home</a>
</nav>
<main>
<p>Page content</p>
</main>
<aside>
<p>Related links</p>
</aside>
Ready to validate your sites?
Start your free trial today.