HTML Guides
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 name attribute is not a valid attribute for the <div> element.
The name attribute is only allowed on specific HTML elements that have a defined use for it, such as <input>, <form>, <iframe>, <object>, <map>, <select>, <textarea>, and <meta>. On these elements, name serves a purpose: identifying form data sent to a server, targeting frames, or referencing image maps.
The <div> element does not accept name. If the goal is to identify or reference a <div>, use the id attribute instead. The id attribute is a global attribute, valid on any HTML element, and provides a unique identifier for styling with CSS, targeting with JavaScript, or linking with fragment URLs.
If the name attribute was being used as a hook for document.getElementsByName(), switching to id with document.getElementById() (or using a class with document.querySelectorAll()) is the correct approach.
Invalid example
<divname="sidebar">
<p>Some content</p>
</div>
Valid example
<divid="sidebar">
<p>Some content</p>
</div>
The name attribute is not a valid attribute for the <span> element in HTML.
The name attribute exists on specific elements like <a>, <form>, <input>, <map>, <meta>, <iframe>, <object>, and <param>. It was never part of the <span> element's specification. In older HTML practices, <a name="section"> was used to create anchor targets within a page, and some developers incorrectly applied the same pattern to <span> elements.
To create an anchor target on a <span> or any other element, use the id attribute instead. The id attribute is a global attribute, valid on every HTML element, and works as a fragment identifier in URLs (e.g., page.html#section-name).
If the name attribute was being used for JavaScript targeting or styling, switch to id, class, or data-* attributes depending on the use case.
Invalid example
<spanname="intro">Welcome to the site.</span>
Valid examples
Use id to create a linkable anchor target:
<spanid="intro">Welcome to the site.</span>
Use class when multiple elements share the same label:
<spanclass="intro">Welcome to the site.</span>
Use a data-* attribute for custom metadata consumed by JavaScript:
<spandata-name="intro">Welcome to the site.</span>
Before HTML5, the way to create a link target within a page was to use a "named anchor" — an <a> element with a name attribute. This allowed other links to jump to that specific spot using a fragment identifier (e.g., href="#section-5"). In HTML5, the name attribute on <a> elements has been marked as obsolete. Instead, the id attribute on any element serves this purpose, making the extra <a> wrapper unnecessary.
This matters for several reasons:
- Standards compliance: Using obsolete attributes means your markup doesn't conform to the current HTML specification, which can cause W3C validation errors.
- Cleaner markup: Named anchors add an extra element that serves no semantic purpose. Using
iddirectly on the target element is simpler and more meaningful. - Accessibility: Screen readers and assistive technologies work better with semantic HTML. An
idon a heading or<section>provides clearer document structure than a nested anchor element. - Browser behavior: While browsers still support
namefor backward compatibility, relying on obsolete features is risky as future browser versions may change or drop support.
To fix this, remove the <a name="..."> element and place an id attribute directly on the nearest appropriate container element, such as a heading (<h2>, <h3>, etc.), a <section>, or a <div>.
Examples
Incorrect: using the obsolete name attribute
<h2>
<aname="section-5">Section 5</a>
</h2>
The <a> element here exists solely to create a link target, adding unnecessary markup.
Correct: using id on the heading
<h2id="section-5">Section 5</h2>
The id attribute on the <h2> makes it a valid fragment link target without any extra elements.
Linking to the section
Both approaches allow navigation via the same fragment URL. The link syntax doesn't change:
<ahref="#section-5">Jump to Section 5</a>
Using id on other container elements
The id attribute works on any HTML element, so you can place it wherever makes the most sense semantically:
<sectionid="contact-info">
<h2>Contact Information</h2>
<p>Email us at hello@example.com.</p>
</section>
Incorrect: multiple named anchors in a document
<p>
<aname="intro">Welcome to our page.</a>
</p>
<p>
<aname="conclusion">Thanks for reading.</a>
</p>
Correct: replacing all named anchors with id attributes
<pid="intro">Welcome to our page.</p>
<pid="conclusion">Thanks for reading.</p>
Remember that id values must be unique within a document — no two elements can share the same id. If you're migrating from name attributes, check for duplicates and ensure each id is used only once.
The name attribute on <a> elements is obsolete in HTML5 and should be replaced with the id attribute.
In older versions of HTML, the name attribute on anchor elements was used to create fragment identifiers — targets you could link to with #section-name in a URL. In HTML5, this approach has been deprecated in favor of the id attribute, which can be placed on any element, not just <a> tags.
Using id is more flexible because you can turn any element into a link target directly, without wrapping it in an anchor. The id attribute works the same way for fragment navigation: a link pointing to #section-name will scroll to the element with id="section-name".
HTML Examples
❌ Obsolete usage with name
<aname="about"></a>
<h2>About Us</h2>
<p>Welcome to our site.</p>
<ahref="#about">Go to About</a>
✅ Fixed using id
<h2id="about">About Us</h2>
<p>Welcome to our site.</p>
<ahref="#about">Go to About</a>
The id attribute is placed directly on the <h2> heading, eliminating the need for an empty <a> tag entirely. The #about link works exactly the same way.
The name attribute was historically used on img elements to reference images through JavaScript's document.images collection or via document.getElementsByName(). In early HTML, name served as an identifier for various elements before the id attribute was widely adopted. The HTML living standard (WHATWG) now marks name as obsolete on img elements, meaning it should no longer be used in new content.
This matters for several reasons:
- Standards compliance: Using obsolete attributes means your HTML does not conform to the current specification, which can cause validation errors and may lead to unexpected behavior in future browser versions.
- Consistency: The
idattribute is the universal mechanism for uniquely identifying any HTML element. Usingidinstead ofnamekeeps your markup consistent and predictable. - JavaScript and CSS targeting: Modern APIs like
document.getElementById()anddocument.querySelector()work withid, notnameon image elements. CSS selectors also target elements byid(e.g.,#myImage), makingidthe more versatile choice. - Fragment linking: The
idattribute allows you to link directly to an element using a URL fragment (e.g.,page.html#myImage), whereas the obsoletenameattribute onimgdoes not serve this purpose.
To fix this issue, simply replace name with id on your img elements. Keep in mind that id values must be unique within the entire document — no two elements can share the same id. If you have JavaScript code that references the image by name (e.g., document.images["myImage"] or document.getElementsByName("myImage")), update those references to use document.getElementById("myImage") or document.querySelector("#myImage") instead.
Examples
Incorrect: using the obsolete name attribute
<imgsrc="photo.jpg"name="heroImage"alt="A sunset over the ocean">
This triggers the validation error because name is no longer a valid attribute on img.
Correct: using the id attribute
<imgsrc="photo.jpg"id="heroImage"alt="A sunset over the ocean">
The name attribute is replaced with id, and the element can now be targeted with document.getElementById("heroImage") or the CSS selector #heroImage.
Updating JavaScript references
If your existing code references the image by name, update it accordingly.
Before (relying on name):
<imgsrc="logo.png"name="siteLogo"alt="Company logo">
<script>
varlogo=document.images["siteLogo"];
logo.style.border="2px solid blue";
</script>
After (using id):
<imgsrc="logo.png"id="siteLogo"alt="Company logo">
<script>
varlogo=document.getElementById("siteLogo");
logo.style.border="2px solid blue";
</script>
Multiple images that previously shared a name
Since id values must be unique, you cannot give the same id to multiple elements. If you previously used the same name on several images and selected them as a group, switch to a shared class instead:
<imgsrc="slide1.jpg"class="gallery-image"alt="Mountain landscape">
<imgsrc="slide2.jpg"class="gallery-image"alt="Forest trail">
<imgsrc="slide3.jpg"class="gallery-image"alt="River valley">
<script>
varimages=document.querySelectorAll(".gallery-image");
images.forEach(function(img){
img.style.borderRadius="8px";
});
</script>
This approach is standards-compliant and gives you flexible, modern element selection using class for groups and id for unique elements.
The name attribute was historically used on <option> elements in older HTML specifications, but it has been obsolete since HTML5. The WHATWG HTML Living Standard does not list name as a valid attribute for <option>. The valid attributes for <option> are disabled, label, selected, and value, in addition to the global attributes (such as id, class, style, etc.).
It's important to understand that the name attribute on <option> never served the same purpose as name on <input> or <select>. For form submission, the browser sends the name from the parent <select> element paired with the value of the selected <option>. Putting name on individual <option> elements has no effect on form data and can mislead developers into thinking it influences form behavior.
Removing the obsolete name attribute ensures your HTML is standards-compliant, avoids confusion for developers maintaining the code, and prevents potential issues with future browser behavior. If you need to reference a specific <option> in JavaScript or CSS, use the id global attribute instead.
Examples
Incorrect: using the obsolete name attribute
<selectid="pet-select"name="pet">
<optionvalue="">--Please choose an option--</option>
<optionname="dog-option"value="dog">Dog</option>
<optionname="cat-option"value="cat">Cat</option>
<optionname="hamster-option"value="hamster">Hamster</option>
</select>
This triggers the validation error because name is not a valid attribute on <option>.
Correct: using id instead of name
If you need to uniquely identify each option (for example, to target them with JavaScript or CSS), use the id attribute:
<selectid="pet-select"name="pet">
<optionvalue="">--Please choose an option--</option>
<optionid="dog-option"value="dog">Dog</option>
<optionid="cat-option"value="cat">Cat</option>
<optionid="hamster-option"value="hamster">Hamster</option>
</select>
Correct: simply removing name if no reference is needed
In most cases, you don't need to identify individual options at all. The value attribute is sufficient for form submission, and you can remove name entirely:
<selectid="pet-select"name="pet">
<optionvalue="">--Please choose an option--</option>
<optionvalue="dog">Dog</option>
<optionvalue="cat">Cat</option>
<optionvalue="hamster">Hamster</option>
</select>
Note that the name attribute on the <select> element itself is perfectly valid and necessary — it defines the key used when the form data is submitted. The obsolete attribute warning applies only to name on <option> elements.
The HTML specification defines certain elements as having implicit ARIA roles — roles that are automatically communicated to assistive technologies without any additional attributes. The nav element is one of these: its implicit role is navigation. When you explicitly add role="navigation" to a nav element, you're telling the browser something it already knows, which clutters your markup without adding any value.
This redundancy matters for several reasons:
- Code maintainability: Unnecessary attributes make your HTML harder to read and maintain. Future developers may wonder if the explicit role is there for a specific reason, creating confusion.
- Standards compliance: The W3C validator warns about this because the ARIA specification follows a principle often summarized as the first rule of ARIA: don't use ARIA if a native HTML element already provides the semantics you need. Extending this principle, don't re-declare semantics that are already present.
- No accessibility benefit: Assistive technologies like screen readers already recognize
navas a navigation landmark. Adding the explicit role doesn't improve the experience for users of these technologies — it's simply noise.
The role="navigation" attribute is useful when applied to a non-semantic element like a div or span that functions as navigation but can't be changed to a nav element (for example, due to legacy constraints). But when you're already using nav, the attribute is unnecessary.
To fix this, remove the role="navigation" attribute from your nav element. The semantic meaning is fully preserved.
Examples
Incorrect: redundant role on nav
This triggers the W3C validator warning because the navigation role is already implicit:
<navrole="navigation">
<ul>
<li><ahref="/">Home</a></li>
<li><ahref="/about">About</a></li>
<li><ahref="/contact">Contact</a></li>
</ul>
</nav>
Correct: nav without the explicit role
Simply remove the redundant role attribute:
<nav>
<ul>
<li><ahref="/">Home</a></li>
<li><ahref="/about">About</a></li>
<li><ahref="/contact">Contact</a></li>
</ul>
</nav>
Correct: using role="navigation" on a non-semantic element
If you cannot use a nav element, applying the role to a div is a valid approach. This does not trigger the warning:
<divrole="navigation">
<ul>
<li><ahref="/">Home</a></li>
<li><ahref="/about">About</a></li>
<li><ahref="/contact">Contact</a></li>
</ul>
</div>
Correct: labeling multiple nav elements
When a page has more than one nav, use aria-label or aria-labelledby to differentiate them for assistive technology users — but still don't add the redundant role:
<navaria-label="Main">
<ul>
<li><ahref="/">Home</a></li>
<li><ahref="/about">About</a></li>
</ul>
</nav>
<navaria-label="Footer">
<ul>
<li><ahref="/privacy">Privacy Policy</a></li>
<li><ahref="/terms">Terms of Service</a></li>
</ul>
</nav>
The <o:p> element is a Microsoft Office namespace tag that has no meaning in HTML and is not part of any HTML specification.
When content is copied from Microsoft Word, Outlook, or other Office applications and pasted into an HTML document, the source often includes proprietary XML namespace elements like <o:p>, <o:OfficeDocumentSettings>, and similar tags. These belong to the urn:schemas-microsoft-com:office:office namespace and are only understood by Office applications. Browsers ignore them, but the W3C validator flags them as errors because they are not valid HTML elements.
The <o:p> tag specifically is used by Word to wrap paragraph content. It typically appears inside <p> elements and most often contains nothing or just a non-breaking space ( ). Removing it entirely has no effect on the rendered page.
If the <o:p> element wraps actual text content, replace it with a standard HTML element like <span> or simply keep the text without any wrapper. If it is empty or contains only , delete it.
HTML examples
Invalid: Office namespace element in HTML
<p>This is a paragraph.<o:p></o:p></p>
<p>
<o:p> </o:p>
</p>
Valid: Office elements removed
<p>This is a paragraph.</p>
When cleaning up Office-generated HTML, also look for other common namespace prefixes like <w:, <m:, and <v:, along with mso- prefixed CSS properties in style attributes. These are all Office artifacts and should be removed. Many text editors and CMS platforms have a "Paste as plain text" option that strips this markup automatically.
The accept-charset attribute on a <form> element only accepts "UTF-8" as its value. Any other character encoding will trigger a validation error.
Older HTML specifications allowed values like "ISO-8859-1", "Windows-1252", or space-separated lists of encodings. The HTML living standard changed this. Now, "UTF-8" is the sole permitted value. Browsers already default to submitting form data in UTF-8 when no accept-charset is specified, so the attribute is rarely needed at all.
If a form currently specifies a non-UTF-8 encoding, the fix is either to switch the value to "UTF-8" or to remove the attribute entirely. Removing it is usually the better choice, since the browser will use UTF-8 by default when the page itself is served as UTF-8 (which it should be).
HTML examples
Invalid usage
<formaction="/search"accept-charset="ISO-8859-1">
<inputtype="text"name="q">
<buttontype="submit">Search</button>
</form>
Valid usage
Remove the attribute and let the browser default to UTF-8:
<formaction="/search">
<inputtype="text"name="q">
<buttontype="submit">Search</button>
</form>
Or explicitly set it to "UTF-8":
<formaction="/search"accept-charset="UTF-8">
<inputtype="text"name="q">
<buttontype="submit">Search</button>
</form>
The meta element's charset attribute only accepts utf-8 as its value in HTML5.
Older HTML versions and XHTML allowed character encodings like windows-1252, iso-8859-1, or shift_jis in the charset attribute. The HTML living standard restricts this to utf-8 only. UTF-8 is the required character encoding for HTML5 documents, and the W3C validator enforces this rule.
If a document actually uses a different encoding, convert the file to UTF-8 using a text editor or command line tool, then update the meta tag accordingly. Most modern text editors can save files as UTF-8.
The <meta charset="utf-8"> declaration should appear as early as possible within the <head> element, ideally as the first child. It must appear within the first 1024 bytes of the document so that browsers can detect the encoding before parsing the rest of the content.
HTML examples
Invalid charset value
<!DOCTYPE html>
<htmllang="en">
<head>
<metacharset="windows-1252">
<title>Example</title>
</head>
<body>
<p>Hello world</p>
</body>
</html>
Valid charset value
<!DOCTYPE html>
<htmllang="en">
<head>
<metacharset="utf-8">
<title>Example</title>
</head>
<body>
<p>Hello world</p>
</body>
</html>
The <param> element is obsolete in HTML5 and should no longer be used inside <object> elements.
The <param> element was originally used to pass named parameters to plugins embedded via <object>, such as Flash, Java applets, or Windows Media Player. Since modern browsers have dropped support for these plugins, the <param> element lost its purpose and was removed from the HTML living standard.
If the <object> element references an external resource like a video, PDF, or image, the resource URL belongs in the data attribute of the <object> element itself. The type attribute should specify the MIME type of the resource.
For media playback, the <video> and <audio> elements are the standard replacements. For other embedded content, <iframe> or <embed> may be more appropriate depending on the use case.
HTML examples
Before: obsolete param element
<object>
<paramname="movie"value="video.mp4">
<paramname="autoplay"value="true">
</object>
After: using the data attribute on object
<objectdata="video.mp4"type="video/mp4">
<p>Your browser does not support this content.</p>
</object>
After: using video for media playback
<videosrc="video.mp4"controls>
<p>Your browser does not support this video.</p>
</video>
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) oraria-label. - Never add explicit ARIA roles that duplicate the implicit role of a native HTML element.
Examples
Incorrect: redundant role on section
<sectionrole="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:
<sectionaria-labelledby="contact-heading">
<h2id="contact-heading">Contact Information</h2>
<p>Email us at info@example.com</p>
</section>
Correct: section with aria-label when no visible heading exists
<sectionaria-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:
<navrole="navigation">
<ahref="/">Home</a>
</nav>
<mainrole="main">
<p>Page content</p>
</main>
<asiderole="complementary">
<p>Related links</p>
</aside>
Correct: landmark elements without redundant roles
<nav>
<ahref="/">Home</a>
</nav>
<main>
<p>Page content</p>
</main>
<aside>
<p>Related links</p>
</aside>
A <tr> element already has an implicit ARIA role of row, so adding role="row" is redundant when the parent <table> uses its default semantics or has a role of table, grid, or treegrid.
HTML tables come with built-in accessibility semantics. The <table> element implicitly has role="table", and <tr> implicitly has role="row". Browsers and assistive technologies already understand this structure, so explicitly adding these roles is unnecessary and flagged by the W3C validator.
The only time you'd need to add a role to a <tr> is when the table's native semantics have been overridden — for example, if the <table> has been repurposed with a non-table role like role="presentation" or role="none". In that case, you'd need explicit ARIA roles to restore row semantics.
Incorrect Example
<table>
<trrole="row">
<th>Name</th>
<th>Email</th>
</tr>
<trrole="row">
<td>Alice</td>
<td>alice@example.com</td>
</tr>
</table>
Fixed Example
Simply remove the redundant role="row" from the <tr> elements:
<table>
<tr>
<th>Name</th>
<th>Email</th>
</tr>
<tr>
<td>Alice</td>
<td>alice@example.com</td>
</tr>
</table>
The same fix applies if your <table> explicitly has role="table", role="grid", or role="treegrid" — the <tr> elements still don't need an explicit role="row" because the browser infers it automatically.
The role attribute is not allowed on a label element when that label is associated with a form control (a labelable element) through the for attribute or by nesting.
When a label is associated with a form control, the browser already understands its purpose — it's a label. Adding a role attribute overrides this native semantics, which is redundant at best and confusing for assistive technologies at worst.
A label becomes "associated" with a labelable element in two ways: explicitly via the for attribute pointing to the control's id, or implicitly by wrapping the control inside the label. Labelable elements include input (except type="hidden"), select, textarea, button, meter, output, and progress.
If the label is associated, simply remove the role attribute. The native semantics are already correct and sufficient.
If you truly need a custom role for some reason and the label is not functionally labeling a control, you can disassociate it by removing the for attribute or unnesting the control — but this is rarely the right approach.
Invalid Example
<labelfor="email"role="presentation">Email</label>
<inputtype="email"id="email">
Valid Example
<labelfor="email">Email</label>
<inputtype="email"id="email">
In older HTML specifications (HTML 4.01), the scheme attribute was used to provide additional context for interpreting the content value of a <meta> element. It told browsers or metadata processors which encoding scheme, format, or vocabulary applied to the metadata. For example, you could specify that a date followed the W3CDTF format or that a subject classification used a particular taxonomy.
HTML5 dropped the scheme attribute because it was rarely used by browsers and its purpose was better served by making the scheme part of the metadata value itself. The WHATWG HTML living standard does not recognize scheme as a valid attribute on <meta>, so including it will produce a validation error. Keeping obsolete attributes in your markup can cause confusion for developers maintaining the code and signals outdated practices that may accompany other compatibility issues.
This issue most commonly appears in documents that use Dublin Core Metadata Initiative (DCMI) metadata, which historically relied on scheme to indicate the encoding format for dates, identifiers, and subject classifications.
How to fix it
There are several approaches depending on your use case:
- Simply remove the
schemeattribute if the format is already clear from context (e.g., ISO 8601 dates are universally understood). - Incorporate the scheme into the
nameattribute by using a more specific property name that implies the scheme. - Include the scheme declaration in the
contentvalue so the format information is preserved within the value itself.
For Dublin Core metadata specifically, the modern recommended approach is to use the DCTERMS namespace with RDFa or to simply drop the scheme attribute, since most date formats like YYYY-MM-DD are unambiguous.
Examples
Obsolete: using the scheme attribute
This triggers the validation error because scheme is not a valid attribute in HTML5:
<metaname="DC.Date.Created"scheme="W3CDTF"content="2009-11-30">
Another common example with subject classification:
<metaname="DC.Subject"scheme="LCSH"content="Web development">
Fixed: removing the scheme attribute
If the value format is self-evident (as with ISO 8601 dates), simply remove scheme:
<metaname="DC.Date.Created"content="2009-11-30">
Fixed: incorporating the scheme into the value
When the scheme information is important for processors to understand the value, embed it in the content attribute:
<metaname="DC.Subject"content="LCSH: Web development">
Fixed: using a more specific property name
You can make the scheme implicit by using a more descriptive name value:
<metaname="DCTERMS.created"content="2009-11-30">
Fixed: using RDFa for richer metadata
For documents that require precise, machine-readable metadata with explicit schemes, consider using RDFa attributes instead of the obsolete scheme:
<metaproperty="dcterms:created"content="2009-11-30">
This approach is compatible with HTML5 and provides the same semantic richness that the scheme attribute was originally designed to offer.
The scope attribute tells browsers and assistive technologies how a header cell relates to the data cells around it. Its valid values are col, row, colgroup, and rowgroup. In older versions of HTML, scope was permitted on <td> elements, but the current HTML Living Standard restricts it to <th> elements only. When the W3C validator encounters scope on a <td>, it flags it as obsolete.
This matters for several reasons. First, if a cell acts as a header for other cells, it should be marked up as a <th>, not a <td>. Using <td scope="row"> sends conflicting signals — the element says "I'm a data cell" while the attribute says "I'm a header for this row." Second, screen readers rely on proper <th> elements with scope to announce table relationships. A <td> with scope may not be interpreted correctly, making the table harder to navigate for users of assistive technology. Third, using obsolete attributes means your markup doesn't conform to current standards, which could lead to unpredictable behavior in future browsers.
The fix is straightforward: if a cell has a scope attribute, it's acting as a header and should be a <th> element. Change the <td> to <th> and keep the scope attribute. If the cell is genuinely a data cell and not a header, remove the scope attribute entirely and leave it as a <td>.
Examples
Incorrect: scope on a <td> element
<table>
<tr>
<tdscope="col">Name</td>
<tdscope="col">Role</td>
</tr>
<tr>
<tdscope="row">Alice</td>
<td>Engineer</td>
</tr>
</table>
This triggers the validation error because scope is used on <td> elements. The first row contains column headers and the first column contains row headers, yet they are all marked as data cells.
Correct: scope on <th> elements
<table>
<tr>
<thscope="col">Name</th>
<thscope="col">Role</th>
</tr>
<tr>
<thscope="row">Alice</th>
<td>Engineer</td>
</tr>
</table>
Now the header cells are correctly marked with <th>, and the scope attribute is valid on each one. Screen readers can properly associate "Alice" with "Engineer" and announce the column header "Role" when navigating to that cell.
A more complete table example
<table>
<thead>
<tr>
<thscope="col">Day</th>
<thscope="col">Morning</th>
<thscope="col">Afternoon</th>
</tr>
</thead>
<tbody>
<tr>
<thscope="row">Monday</th>
<td>Meeting</td>
<td>Code review</td>
</tr>
<tr>
<thscope="row">Tuesday</th>
<td>Workshop</td>
<td>Planning</td>
</tr>
</tbody>
</table>
Here, scope="col" on the column headers in <thead> tells assistive technology that "Day," "Morning," and "Afternoon" each apply to the cells below them. scope="row" on "Monday" and "Tuesday" indicates they apply to the cells in their respective rows. Every scope attribute sits on a <th>, so the markup is valid and accessible.
When to remove scope instead
If the cell truly contains data and isn't a header, simply remove the scope attribute:
<!-- Before (invalid) -->
<tdscope="row">Some data</td>
<!-- After (valid) -->
<td>Some data</td>
Only add scope when a cell genuinely serves as a header. If it does, make it a <th>. If it doesn't, leave it as a plain <td> without scope.
Every HTML element carries an implicit ARIA role based on its type and attributes. For <input type="search"> elements that do not have a list attribute, the browser automatically exposes the element with the searchbox role to assistive technologies. This mapping is defined in the ARIA in HTML specification, which establishes the correspondence between native HTML semantics and ARIA roles.
When you explicitly add role="searchbox" to an element that already carries that role implicitly, the validator raises a warning because the attribute is doing nothing useful. While it won't break functionality, redundant roles clutter your markup and can signal to other developers (or future you) that something special is intended when it isn't. Following the general principle of ARIA — "don't use ARIA if you can use native HTML" — also means not restating what the browser already communicates.
Note the distinction the validator makes: this applies specifically to <input type="search"> elements without a list attribute. When a list attribute is present (linking the input to a <datalist>), the implicit role changes to combobox, so in that specific scenario the implicit role is different. However, for a plain search input without list, the searchbox role is already baked in.
Why it matters
- Standards compliance: The W3C validator flags redundant roles to encourage clean, semantic markup that relies on native HTML behavior.
- Maintainability: Redundant attributes add noise. Other developers may wonder why the role was explicitly set and whether removing it would break something.
- ARIA best practices: The first rule of ARIA is to use native HTML semantics whenever possible. Restating implicit roles goes against this principle and can mask situations where an explicit role would actually be meaningful.
How to fix it
Simply remove the role="searchbox" attribute from any <input type="search"> element that does not have a list attribute. The browser and assistive technologies will continue to treat it as a search box.
Examples
Incorrect — redundant role
The role="searchbox" is unnecessary here because <input type="search"> already implies it:
<labelfor="site-search">Search the site:</label>
<inputtype="search"id="site-search"role="searchbox"placeholder="Search...">
Correct — relying on implicit role
Remove the redundant role attribute and let native HTML semantics do the work:
<labelfor="site-search">Search the site:</label>
<inputtype="search"id="site-search"placeholder="Search...">
Correct — explicit role when implicit role differs
When a list attribute is present, the implicit role changes to combobox. If you want assistive technologies to treat it as a searchbox instead, an explicit role is justified:
<labelfor="city-search">Search cities:</label>
<inputtype="search"id="city-search"list="cities"role="searchbox">
<datalistid="cities">
<optionvalue="Amsterdam">
<optionvalue="Berlin">
<optionvalue="Cairo">
</datalist>
In this case, the validator will not flag the role as redundant because the implicit role (combobox) differs from the explicitly set role (searchbox).
The <select> element provides a menu of options for the user. By default, it operates as a single-selection control — the user can pick exactly one option from the list. The selected attribute on an <option> element indicates which option should be pre-selected when the page loads. When two or more <option> elements have the selected attribute inside a single-choice <select>, this creates an invalid and contradictory state: the browser is told to pre-select multiple items in a control that only supports one selection.
When browsers encounter this contradiction, their behavior is inconsistent. Most will silently pick the last <option> marked as selected and ignore the others, but this is not guaranteed by the specification. Relying on undefined behavior leads to unpredictable results across browsers and can confuse both users and developers about which value will actually be submitted with a form.
From an accessibility standpoint, assistive technologies may announce the selected state of options to users. Multiple selected attributes on a single-choice <select> can cause screen readers to provide misleading or confusing information about which option is currently active.
The HTML specification (WHATWG) explicitly states that if the multiple attribute is absent, no more than one <option> descendant of the <select> may have the selected attribute.
How to fix it
You have two options depending on your intent:
- If only one option should be pre-selected: Remove the
selectedattribute from all but one<option>. This keeps the<select>as a standard single-choice dropdown. - If multiple options should be pre-selected: Add the
multipleattribute to the<select>element. This changes the control from a dropdown to a list box where users can select multiple items (typically by holding Ctrl or Cmd while clicking). Keep in mind that this changes the visual appearance and interaction model of the control, so make sure it fits your design and use case.
Examples
Incorrect: multiple selected options without multiple
This triggers the validation error because two options are marked as selected in a single-choice <select>:
<selectname="color">
<optionvalue="red"selected>Red</option>
<optionvalue="green"selected>Green</option>
<optionvalue="blue">Blue</option>
</select>
Correct: only one selected option
If the intent is a single-choice dropdown, keep selected on only one <option>:
<selectname="color">
<optionvalue="red"selected>Red</option>
<optionvalue="green">Green</option>
<optionvalue="blue">Blue</option>
</select>
Correct: multiple selected options with the multiple attribute
If the intent is to allow multi-selection and pre-select more than one option, add the multiple attribute:
<selectname="color"multiple>
<optionvalue="red"selected>Red</option>
<optionvalue="green"selected>Green</option>
<optionvalue="blue">Blue</option>
</select>
Correct: no selected attribute at all
If you don't need any option pre-selected, you can omit selected entirely. The browser will typically display the first <option> by default:
<selectname="color">
<optionvalue="">Choose a color</option>
<optionvalue="red">Red</option>
<optionvalue="green">Green</option>
<optionvalue="blue">Blue</option>
</select>
In older versions of HTML, the <a> element supported a shape attribute (with values like rect, circle, poly, and default) to define clickable hotspot regions within an image map. This feature was removed from the HTML specification, and the shape attribute is now considered obsolete on <a> elements.
The modern and correct way to create image maps is to use the <map> element containing one or more <area> elements. Each <area> element accepts a shape attribute along with coords to define clickable regions, and an href to specify the link destination. The <img> element is then associated with the map via its usemap attribute.
Why this matters
- Standards compliance: The
shapeattribute on<a>is not part of the current HTML living standard. Using it produces a validation error and relies on deprecated behavior that browsers are not required to support. - Browser compatibility: Modern browsers implement image maps through
<map>and<area>. Using the obsolete<a shape="...">syntax may not work reliably across browsers. - Accessibility: The
<area>element is designed to work with assistive technologies in the context of image maps. It supports thealtattribute, which provides text alternatives for each clickable region — something essential for screen reader users.
How to fix it
- Remove the
shapeattribute from any<a>elements. - Create a
<map>element with a uniquenameattribute. - Inside the
<map>, add<area>elements with the appropriateshape,coords,href, andaltattributes. - Associate the map with an
<img>element using theusemapattribute, referencing the map'snamewith a#prefix.
Examples
Incorrect: using shape on an <a> element
<imgsrc="workspace.png"usemap="#workspace"alt="Workspace diagram"width="400"height="300">
<mapname="workspace">
<ashape="rect"coords="0,0,200,150"href="/monitor.html">Monitor</a>
<ashape="circle"coords="300,200,50"href="/lamp.html">Desk lamp</a>
</map>
This triggers the validation error because the shape attribute is obsolete on <a> elements.
Correct: using <area> elements instead
<imgsrc="workspace.png"usemap="#workspace"alt="Workspace diagram"width="400"height="300">
<mapname="workspace">
<areashape="rect"coords="0,0,200,150"href="/monitor.html"alt="Monitor">
<areashape="circle"coords="300,200,50"href="/lamp.html"alt="Desk lamp">
</map>
Each <area> element defines a clickable region with shape and coords, links to a destination with href, and provides an accessible label with alt. The <area> element is a void element (no closing tag needed), and the alt attribute is required when href is present.
Supported shape values on <area>
| Value | Description | coords format |
|---|---|---|
rect | A rectangle | x1,y1,x2,y2 |
circle | A circle | centerX,centerY,radius |
poly | A polygon defined by multiple points | x1,y1,x2,y2,...,xn,yn |
default | The entire image area not covered by other shapes | No coords needed |
Example with multiple shape types
<imgsrc="floorplan.png"usemap="#floorplan"alt="Office floor plan"width="600"height="400">
<mapname="floorplan">
<areashape="rect"coords="10,10,200,150"href="/conference-room.html"alt="Conference room">
<areashape="circle"coords="400,300,60"href="/break-room.html"alt="Break room">
<areashape="poly"coords="300,10,350,80,250,80"href="/lobby.html"alt="Lobby">
<areashape="default"href="/office-overview.html"alt="General office area">
</map>
This example demonstrates all four shape types working together in a single image map, with proper alt text for each clickable region.
The sizes attribute and the srcset attribute work together as a system for responsive images. The srcset attribute provides the browser with a list of image candidates (typically at different widths or pixel densities), while the sizes attribute tells the browser how much space the image will occupy in the layout. The browser uses both pieces of information together to pick the most appropriate image file to download.
When you specify sizes without srcset, the attribute has no purpose. There's only one image source (the src attribute), so the browser has nothing to choose from, and the layout hints provided by sizes are meaningless. The HTML specification explicitly states that the sizes attribute must not be present unless srcset is also specified with width descriptors (w). This isn't just a stylistic concern — it signals to validators and other tools that the markup is incomplete or incorrect, which could indicate a copy-paste error or a missing attribute.
This issue commonly occurs when:
- The
srcsetattribute is accidentally removed during refactoring, leavingsizesorphaned. - A developer adds
sizesin preparation for responsive images but forgets to addsrcset. - Code is copied from a template and partially modified.
Examples
❌ Invalid: sizes without srcset
<img
src="photo.jpg"
sizes="(max-width: 600px) 100vw, 50vw"
alt="A landscape photo">
The sizes attribute is present, but there is no srcset to provide multiple image candidates. The browser has no use for the sizing information.
✅ Fix: Add a matching srcset attribute
<img
src="photo.jpg"
srcset="photo-400.jpg 400w, photo-800.jpg 800w, photo-1200.jpg 1200w"
sizes="(max-width: 600px) 100vw, 50vw"
alt="A landscape photo">
Now sizes tells the browser: "Below 600px viewports, the image fills 100% of the viewport width; otherwise it fills 50%." The browser combines this with the width descriptors in srcset to select the best image.
✅ Fix: Remove sizes if you don't need responsive images
<img
src="photo.jpg"
alt="A landscape photo">
If you only have a single image source and don't need responsive behavior, simply remove the sizes attribute.
✅ Using sizes with <source> inside <picture>
The same rule applies to <source> elements inside a <picture> block:
<picture>
<source
srcset="photo-dark-400.jpg 400w, photo-dark-800.jpg 800w"
sizes="(max-width: 600px) 100vw, 50vw"
media="(prefers-color-scheme: dark)">
<img
src="photo.jpg"
srcset="photo-400.jpg 400w, photo-800.jpg 800w"
sizes="(max-width: 600px) 100vw, 50vw"
alt="A landscape photo">
</picture>
Each element that uses sizes also includes a corresponding srcset with width descriptors.
A note on srcset with pixel density descriptors
The sizes attribute is specifically designed for use with width descriptors (w) in srcset. If you're using pixel density descriptors (x) instead, sizes is not needed:
<img
src="photo.jpg"
srcset="photo-2x.jpg 2x, photo-3x.jpg 3x"
alt="A landscape photo">
In this case, the browser selects based on device pixel ratio rather than viewport size, so sizes would be unnecessary.
The sizes attribute and the srcset attribute are designed to work as a pair for responsive image delivery. The srcset attribute provides the browser with a list of image files and their intrinsic widths (e.g., 480w, 800w), while the sizes attribute tells the browser how much space the image will occupy in the layout at different viewport sizes. The browser combines this information to select the most appropriate image file to download.
When sizes appears without srcset, it serves no purpose. The browser has only the single image specified in the src attribute, so there's no decision to make about which image to load. The HTML specification explicitly requires that sizes must not be present unless srcset is also specified with width descriptors.
This error commonly occurs when a CMS or templating system outputs the sizes attribute by default, when srcset is accidentally removed during refactoring, or when developers copy markup snippets without including all the necessary attributes.
Beyond standards compliance, leaving orphaned sizes attributes creates confusing, harder-to-maintain code. Other developers (or your future self) may assume responsive images are configured when they aren't, leading to wasted debugging time.
How to fix it
You have two options:
- Add a
srcsetattribute if you want the browser to choose from multiple image sizes based on viewport width. Thesrcsetmust use width descriptors (w) forsizesto be meaningful. - Remove the
sizesattribute if you don't need responsive images and a singlesrcis sufficient.
Note that sizes is also valid on <source> elements inside a <picture> element — the same rule applies there. Every <source> with a sizes attribute must also have a srcset attribute.
Examples
❌ Incorrect: sizes without srcset
<img
src="image.jpg"
sizes="(max-width: 600px) 480px, 800px"
alt="A mountain landscape">
The sizes attribute is present but there's no srcset, so the browser has no alternative images to pick from.
✅ Correct: sizes paired with srcset
<img
src="image-800w.jpg"
srcset="image-480w.jpg 480w, image-800w.jpg 800w"
sizes="(max-width: 600px) 480px, 800px"
alt="A mountain landscape">
Here, srcset provides two images with their intrinsic widths. The sizes attribute tells the browser: "If the viewport is 600px or narrower, the image will display at 480px wide; otherwise, it will display at 800px wide." The browser uses this information to download the most efficient file.
✅ Correct: removing sizes when responsive images aren't needed
<imgsrc="image.jpg"alt="A mountain landscape">
If a single image is sufficient, simply drop the sizes attribute.
❌ Incorrect: sizes on a <source> without srcset
<picture>
<source
media="(min-width: 800px)"
sizes="50vw">
<imgsrc="fallback.jpg"alt="A sunset over the ocean">
</picture>
✅ Correct: sizes on a <source> with srcset
<picture>
<source
media="(min-width: 800px)"
srcset="wide-480w.jpg 480w, wide-960w.jpg 960w"
sizes="50vw">
<imgsrc="fallback.jpg"alt="A sunset over the ocean">
</picture>
The <source> element now includes a srcset with width descriptors, giving the browser the candidate images it needs to make use of sizes.
The summary attribute was used in HTML 4 to provide a text description of a table's structure and purpose, primarily for screen reader users. In HTML5, this attribute was deprecated because it was invisible to sighted users, creating an unequal experience. It was also frequently misused — authors often duplicated the table's caption or provided unhelpful descriptions, diminishing its accessibility value.
The HTML Living Standard offers several better alternatives, each suited to different situations:
- Use a
<caption>element — Best for a concise title or description that benefits all users, not just screen reader users. The<caption>must be the first child of the<table>element. - Use a
<figure>with<figcaption>— Ideal when you want to provide a longer description or contextual information alongside the table. This approach also semantically groups the table with its description. - Simplify the table — If your table is straightforward with clear headers, it may not need any additional description at all. Well-structured
<th>elements with appropriatescopeattributes often provide enough context.
From an accessibility standpoint, the <caption> and <figcaption> approaches are superior because they are visible to all users and part of the document flow. Screen readers announce <caption> content when a user navigates to a table, providing the same benefit the summary attribute once offered — but now everyone can see it.
Examples
❌ Obsolete: Using the summary attribute
This triggers the validation warning because summary is no longer a valid attribute on <table>.
<tablesummary="This table shows monthly sales figures for 2024.">
<tr>
<th>Month</th>
<th>Sales</th>
</tr>
<tr>
<td>January</td>
<td>$1,000</td>
</tr>
<tr>
<td>February</td>
<td>$1,200</td>
</tr>
</table>
✅ Fix 1: Using a <caption> element
Replace the summary attribute with a <caption> as the first child of the <table>. This is the most common and straightforward fix.
<table>
<caption>Monthly sales figures for 2024</caption>
<tr>
<th>Month</th>
<th>Sales</th>
</tr>
<tr>
<td>January</td>
<td>$1,000</td>
</tr>
<tr>
<td>February</td>
<td>$1,200</td>
</tr>
</table>
✅ Fix 2: Using <figure> and <figcaption>
This approach is useful when you want to provide a longer description or when the table is referenced as a figure within surrounding content.
<figure>
<figcaption>
Monthly sales figures for 2024, showing a steady increase in revenue
during the first quarter.
</figcaption>
<table>
<tr>
<th>Month</th>
<th>Sales</th>
</tr>
<tr>
<td>January</td>
<td>$1,000</td>
</tr>
<tr>
<td>February</td>
<td>$1,200</td>
</tr>
</table>
</figure>
✅ Fix 3: Simplify and rely on clear headers
For simple tables where the data is self-explanatory, well-labeled headers with scope attributes may be sufficient. No extra description is needed.
<table>
<thead>
<tr>
<thscope="col">Month</th>
<thscope="col">Sales</th>
</tr>
</thead>
<tbody>
<tr>
<td>January</td>
<td>$1,000</td>
</tr>
<tr>
<td>February</td>
<td>$1,200</td>
</tr>
</tbody>
</table>
You can also combine approaches — use a <caption> for a brief title and wrap the table in a <figure> with a <figcaption> for additional context. The key takeaway is to remove the summary attribute and use visible, semantic HTML elements to describe your table instead.
The role="table" attribute on a <table> element is redundant because the <table> element already has an implicit ARIA role of table.
Every HTML element carries a default ARIA role defined by the HTML specification. The <table> element's built-in role is table, so adding role="table" explicitly tells assistive technologies something they already know. The W3C validator flags this as unnecessary markup.
This applies to many other elements too. A <nav> element has an implicit role of navigation, a <button> has a role of button, and so on. Adding these explicit roles creates noise in the code without any accessibility benefit.
Incorrect example
<tablerole="table">
<tr>
<th>Name</th>
<th>Age</th>
</tr>
<tr>
<td>Alice</td>
<td>30</td>
</tr>
</table>
Fixed example
<table>
<tr>
<th>Name</th>
<th>Age</th>
</tr>
<tr>
<td>Alice</td>
<td>30</td>
</tr>
</table>
The <time> element represents a specific moment or duration in time. Browsers, search engines, and assistive technologies rely on parsing its value to understand temporal data programmatically. The element can get its machine-readable value from two places: the datetime attribute, or, if that attribute is absent, from the element's text content directly.
When there is no datetime attribute, the text content itself must be in one of the valid formats specified by the HTML standard. This is where the error typically occurs—authors write a human-readable date like "March 20, 2025" or "last Tuesday" as the text content without providing a datetime attribute, and the validator rejects it because that string isn't machine-parsable.
Why This Matters
- Machine readability: Search engines (via structured data) and browser features (like calendar integration) depend on parsing the
<time>element's value. An invalid format means these tools can't understand the date or time. - Accessibility: Screen readers and other assistive technologies may use the machine-readable datetime to present temporal information more helpfully to users.
- Standards compliance: The HTML specification explicitly defines which formats are valid. Using anything else makes your document non-conforming.
How to Fix It
You have two options:
- Add a
datetimeattribute with the machine-readable value, and keep the human-readable text as the visible content. This is the most common and practical approach. - Use a valid format directly as the text content if you don't mind displaying a machine-readable format to users.
Valid Formats
Here is a reference of accepted formats for the <time> element:
| Type | Example(s) |
|---|---|
| Valid year | 2011 |
| Valid month | 2011-11 |
| Valid date | 2011-11-18 |
| Valid yearless date | 11-18 |
| Valid week | 2011-W47 |
| Valid time | 14:54, 14:54:39, 14:54:39.929 |
| Valid local date and time | 2011-11-18T14:54:39.929 or 2011-11-18 14:54:39.929 |
| Valid global date and time | 2011-11-18T14:54:39.929Z, 2011-11-18T14:54:39.929-04:00 |
| Valid duration | PT4H18M3S, P2D (2 days), P3DT4H (3 days, 4 hours) |
Examples
Incorrect: Human-readable text without datetime attribute
The validator will report the error because "March 20, 2025" is not a valid machine-readable format:
<p>The concert is on <time>March 20, 2025</time>.</p>
Incorrect: Informal text as content
Similarly, casual date strings are not valid:
<p>Updated <time>last Friday</time>.</p>
Correct: Using the datetime attribute
Add a datetime attribute with the machine-readable value and keep the human-friendly text visible:
<p>The concert is on <timedatetime="2025-03-20">March 20, 2025</time>.</p>
Correct: Including time and timezone
<p>
The event starts at
<timedatetime="2025-03-20T13:00-05:00">1:00 PM EST on March 20, 2025</time>.
</p>
Correct: Machine-readable format as text content
If no datetime attribute is provided, the text content itself must be a valid format:
<p>Date: <time>2025-03-20</time></p>
Correct: Representing a duration
<p>Cooking time: <timedatetime="PT1H30M">1 hour and 30 minutes</time>.</p>
Correct: Using just a time value
<p>The shop opens at <time>09:00</time> every day.</p>
As a general rule, whenever you want to display a date or time in a natural, human-friendly way, always pair it with a datetime attribute that contains the machine-readable equivalent. This keeps your HTML valid, your content accessible, and your temporal data useful to machines.
When you use semantic HTML elements, browsers automatically assign appropriate ARIA roles behind the scenes. An <input type="text"> element without a list attribute is inherently recognized by browsers and assistive technologies as a textbox — a control that accepts free-form text input. Explicitly declaring role="textbox" on such an element repeats information that is already conveyed natively, which is what the validator flags.
The distinction about the list attribute matters because when an <input type="text"> does have a list attribute (linking it to a <datalist>), its implicit role changes to combobox rather than textbox. In that scenario, a role="textbox" would not only be redundant — it would actually be incorrect. The validator's message specifically targets the case where there is no list attribute, meaning the implicit role is already textbox.
Why this is a problem
- Redundancy clutters your code. Adding roles that elements already possess makes HTML harder to read and maintain without providing any benefit.
- Potential for confusion. Other developers (or your future self) may wonder if the explicit role was added intentionally to override some other behavior, leading to unnecessary investigation.
- Standards compliance. The W3C and WAI-ARIA authoring practices recommend against setting ARIA roles that duplicate the native semantics of an element. The first rule of ARIA use is: "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."
- No accessibility benefit. Assistive technologies already understand that
<input type="text">is a textbox. The explicit role adds no additional information for screen readers or other tools.
How to fix it
Simply remove the role="textbox" attribute from your <input type="text"> element. The native semantics of the element are sufficient.
If you've added the role because the input is styled or behaves differently, consider whether you actually need a different element or a different ARIA pattern instead.
Examples
❌ Incorrect: redundant role="textbox"
<labelfor="username">Username</label>
<inputtype="text"id="username"role="textbox">
The role="textbox" is unnecessary here because <input type="text"> without a list attribute already has an implicit role of textbox.
✅ Correct: no explicit role needed
<labelfor="username">Username</label>
<inputtype="text"id="username">
✅ Also correct: input with list attribute (different implicit role)
<labelfor="color">Favorite color</label>
<inputtype="text"id="color"list="colors">
<datalistid="colors">
<optionvalue="Red">
<optionvalue="Green">
<optionvalue="Blue">
</datalist>
In this case, the list attribute changes the implicit role to combobox, so the validator warning about a redundant textbox role would not apply. Note that adding role="textbox" here would be incorrect rather than merely redundant, since it would override the proper combobox semantics.
❌ Incorrect: redundant role on implicit text input
<labelfor="search-field">Search</label>
<inputid="search-field"role="textbox">
When the type attribute is omitted, <input> defaults to type="text", so the implicit role is still textbox and the explicit role remains redundant.
✅ Correct: let the default type handle semantics
<labelfor="search-field">Search</label>
<inputid="search-field">
Validate at scale.
Ship accessible websites, faster.
Automated HTML & accessibility validation for large sites. Check thousands of pages against WCAG guidelines and W3C standards in minutes, not days.
Pro Trial
Full Pro access. Cancel anytime.
Start Pro Trial →Join teams across 40+ countries