HTML Guides for article
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 <article> element is meant to wrap independent, self-contained content such as blog posts, news stories, forum posts, product cards, or user comments. The W3C validator raises this warning because an <article> without a heading has no programmatic label, making it harder for users—especially those relying on screen readers—to understand what the article is about and to navigate between multiple articles on a page.
Screen readers often present a list of landmarks and headings to help users jump through a page’s structure. When an <article> has no heading, it appears as an unlabeled region, which is confusing and defeats the purpose of using semantic HTML. A heading inside the <article> acts as its identifying title, giving both sighted users and assistive technology a clear summary of the content that follows.
This is a warning rather than a hard validation error, but it signals a real accessibility and usability concern. In nearly all cases, every <article> should contain a heading. The heading level you choose should fit logically within the document’s heading hierarchy—typically <h2> if the <article> sits directly under the page’s main <h1>, or <h3> if it’s nested inside a section that already uses <h2>.
How to fix it
- Add a heading element (<h2>–<h6>) as one of the first children inside each <article>.
- Choose the correct heading level based on the document outline. Don’t skip levels (e.g., jumping from <h1> to <h4>).
- Make the heading descriptive. It should clearly summarize the article’s content.
If your design doesn’t visually display a heading, you can use CSS to visually hide it while keeping it accessible to screen readers (see the examples below).
Examples
❌ Article without a heading (triggers the warning)
<h1>Latest news</h1>
<article>
<p>Our new product launched today with great success.</p>
</article>
<article>
<p>We are hiring frontend developers. Apply now!</p>
</article>
Each <article> here has no heading, so assistive technologies cannot identify them, and the validator raises a warning.
✅ Articles with proper headings
<h1>Latest news</h1>
<article>
<h2>Product launch a success</h2>
<p>Our new product launched today with great success.</p>
</article>
<article>
<h2>We're hiring frontend developers</h2>
<p>We are hiring frontend developers. Apply now!</p>
</article>
✅ Nested articles with correct heading hierarchy
<h1>Our blog</h1>
<article>
<h2>How to validate accessibility</h2>
<p>Use automated tools for an in-depth scan of your site.</p>
<section>
<h3>Comments</h3>
<article>
<h4>Comment by Alex</h4>
<p>Great article, very helpful!</p>
</article>
</section>
</article>
When articles are nested (e.g., comments inside a blog post), each level gets the next heading level to maintain a logical outline.
✅ Visually hidden heading for design flexibility
If your design doesn’t call for a visible heading but you still need one for accessibility, use a CSS utility class to hide it visually while keeping it in the accessibility tree:
<style>
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
</style>
<article>
<h2 class="visually-hidden">Featured promotion</h2>
<p>Save 20% on all items this weekend only!</p>
</article>
This approach satisfies both the validator and assistive technologies without affecting your visual layout. Avoid using display: none or visibility: hidden, as those also hide the heading from screen readers.
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.
Using the ARIA role value listitem on an article element is invalid.
The article element is a landmark with an implicit role of article, and ARIA requires roles to match the element’s semantics. The listitem role is only valid for elements that are direct children of a list-type container with role list or group, or native lists like ul/ol. If you want an article in a list, wrap each article in a proper list container and either rely on native semantics (ul/ol) or use a neutral container with an explicit role="list". Avoid overriding landmark elements with unrelated roles. Use the role attribute only when necessary, and prefer native HTML semantics.
HTML Examples
Invalid: article with role=”listitem”
<article role="listitem">
<h2>News item</h2>
<p>Details...</p>
</article>
Valid options
<!-- Option A: Use native list semantics -->
<ul>
<li>
<article>
<h2>News item</h2>
<p>Details...</p>
</article>
</li>
<li>
<article>
<h2>Another item</h2>
<p>More details...</p>
</article>
</li>
</ul>
<!-- Option B: ARIA list with neutral containers -->
<div role="list">
<div role="listitem">
<article>
<h2>News item</h2>
<p>Details...</p>
</article>
</div>
<div role="listitem">
<article>
<h2>Another item</h2>
<p>More details...</p>
</article>
</div>
</div>
The role="tabpanel" attribute is not permitted on the article element according to W3C and WHATWG HTML specifications.
The role attribute helps describe the purpose of an element for assistive technologies. The value tabpanel indicates a section of a tab interface and should be used only with elements suited to that role—typically generic containers like div or section, not article. The article element has its own landmark meaning and should not be used for widgets such as tab panels.
Correct usage:
- Use role="tabpanel" on a div or section element.
- Use role="tablist" on the container of the tabs.
- Use role="tab" on each tab.
Incorrect:
<article role="tabpanel" id="panel1">
Tab panel content here.
</article>
Correct:
<div role="tabpanel" id="panel1">
Tab panel content here.
</div>
Full example:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Tabpanel Example</title>
</head>
<body>
<div role="tablist">
<button role="tab" aria-controls="panel1" aria-selected="true">Tab 1</button>
<button role="tab" aria-controls="panel2" aria-selected="false">Tab 2</button>
</div>
<div role="tabpanel" id="panel1">
Tab panel content here.
</div>
<div role="tabpanel" id="panel2" hidden>
Tab panel 2 content here.
</div>
</body>
</html>
Replace the article element with a div or section when assigning the tabpanel role to ensure your markup is valid and accessible.
Every HTML semantic element carries an implicit ARIA role that assistive technologies already recognize. The <article> element has a built-in role of article, which signals that the content represents a self-contained composition — such as a blog post, news story, forum comment, or any section that could be independently distributed or reused. When you explicitly add role="article" to an <article> element, you’re telling the browser and screen readers something they already know.
While this redundancy won’t break anything functionally, it creates unnecessary noise in your markup and goes against the W3C’s guidance on using ARIA. The first rule of ARIA use states: “If you can use a native HTML element or attribute with the semantics and behavior you require already built in, instead of repurposing an element and adding an ARIA role, state or property to make it accessible, then do so.” Redundant roles make code harder to maintain and can signal to other developers that something non-standard is happening when it isn’t.
The role="article" attribute is useful when applied to non-semantic elements like <div> or <span> that need to convey article semantics — for instance, in legacy codebases where changing the element isn’t feasible. But on the <article> element itself, it should simply be removed.
Examples
❌ Redundant role on <article>
This triggers the validator warning because role="article" duplicates the element’s implicit role:
<article role="article">
<h2>Breaking News</h2>
<p>A rare bird was spotted in the city park this morning.</p>
</article>
✅ Fixed: no explicit role needed
Simply remove the role attribute. The <article> element already communicates the article role to assistive technologies:
<article>
<h2>Breaking News</h2>
<p>A rare bird was spotted in the city park this morning.</p>
</article>
✅ Appropriate use of role="article" on a non-semantic element
If you cannot use the <article> element for some reason, applying the role to a generic element like <div> is valid and useful:
<div role="article">
<h2>Breaking News</h2>
<p>A rare bird was spotted in the city park this morning.</p>
</div>
✅ Multiple articles within a feed
A common pattern is nesting several <article> elements inside a feed. No explicit roles are needed on the articles themselves:
<section role="feed" aria-label="Latest posts">
<article>
<h2>First Post</h2>
<p>Content of the first post.</p>
</article>
<article>
<h2>Second Post</h2>
<p>Content of the second post.</p>
</article>
</section>
This same principle applies to other semantic elements with implicit roles — for example, <nav> already has role="navigation", <main> has role="main", and <header> has role="banner". Avoid adding redundant roles to any of these elements to keep your HTML clean and standards-compliant.
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.
Ready to validate your sites?
Start your free trial today.