HTML Guides for textbox
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 textbox ARIA role identifies an element that allows free-form text input. While it can technically be applied to elements using contenteditable, it should not be placed on elements that already carry strong semantic meaning, such as <li>. A list item is expected to be a child of <ul>, <ol>, or <menu>, and its implicit listitem role communicates its purpose within a list structure to assistive technologies. Assigning role="textbox" to an <li> overrides this semantic, confusing screen readers and other assistive tools about whether the element is a list item or a text input field.
This is problematic for several reasons:
- Accessibility: Screen readers rely on roles to convey the purpose of elements to users. An <li> with role="textbox" sends mixed signals — it exists within a list structure but announces itself as a text input.
- Standards compliance: The ARIA in HTML specification restricts which roles can be applied to specific elements. The li element does not allow the textbox role, which is why the W3C validator flags this as an error.
- Browser behavior: Browsers may handle the conflicting semantics unpredictably, leading to inconsistent experiences across different user agents.
The best approach is to use native HTML form elements whenever possible. The <input type="text"> element handles single-line text input, and the <textarea> element handles multi-line input. These native elements come with built-in keyboard support, focus management, and form submission behavior — none of which you get for free with a role="textbox" on a non-form element.
If you genuinely need an editable area inside a list and cannot use native form elements, nest a <div> or <span> with role="textbox" inside the <li> rather than placing the role on the <li> itself.
Examples
❌ Incorrect: role="textbox" on an li element
<ul>
<li role="textbox" contenteditable="true">Edit this item</li>
<li role="textbox" contenteditable="true">Edit this item too</li>
</ul>
This triggers the validator error because textbox is not a valid role for <li>.
✅ Fix: Use native form elements
The simplest and most robust fix is to use standard form controls:
<ul>
<li>
<label for="item1">Item 1:</label>
<input type="text" id="item1" value="Edit this item">
</li>
<li>
<label for="item2">Item 2:</label>
<input type="text" id="item2" value="Edit this item too">
</li>
</ul>
For multi-line input, use <textarea>:
<ul>
<li>
<label for="note1">Note:</label>
<textarea id="note1">Edit this content</textarea>
</li>
</ul>
✅ Fix: Nest a div with role="textbox" inside the li
If you need a contenteditable area and cannot use native form elements, place the textbox role on a nested element:
<ul>
<li>
<div id="label1">Item 1:</div>
<div
role="textbox"
contenteditable="true"
aria-labelledby="label1"
aria-placeholder="Enter text">
Edit this item
</div>
</li>
</ul>
This preserves the <li> element’s implicit listitem role while correctly assigning the textbox role to a semantically neutral <div>.
✅ Fix: Remove the list structure entirely
If the items aren’t truly a list, consider dropping the <ul>/<li> structure altogether:
<div id="zipLabel">Enter your five-digit zipcode</div>
<div
role="textbox"
contenteditable="true"
aria-placeholder="5-digit zipcode"
aria-labelledby="zipLabel">
</div>
In every case, prefer native <input> and <textarea> elements over role="textbox" with contenteditable. Native elements provide accessible behavior by default, including keyboard interaction, form validation, and proper focus management, without requiring additional ARIA attributes or JavaScript.
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"
<label for="username">Username</label>
<input type="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
<label for="username">Username</label>
<input type="text" id="username">
✅ Also correct: input with list attribute (different implicit role)
<label for="color">Favorite color</label>
<input type="text" id="color" list="colors">
<datalist id="colors">
<option value="Red">
<option value="Green">
<option value="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
<label for="search-field">Search</label>
<input id="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
<label for="search-field">Search</label>
<input id="search-field">
Ready to validate your sites?
Start your free trial today.