HTML Guides for aria-required
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 HTML required attribute was introduced in HTML5 and tells both the browser and assistive technologies that a form field must be filled in before the form can be submitted. The aria-required attribute serves the same purpose but comes from the WAI-ARIA specification, which was designed to fill accessibility gaps in HTML. Now that required is widely supported, using both attributes on the same element is unnecessary duplication.
The W3C validator raises this warning because redundant ARIA attributes add noise to your markup without providing any benefit. One of the core principles of ARIA usage is the first rule of ARIA: if you can use a native HTML element or attribute that already has the semantics you need, use that instead of adding ARIA. The native required attribute provides built-in browser validation, visual cues, and accessibility information all at once — something aria-required alone cannot do.
Modern screen readers such as NVDA, JAWS, and VoiceOver all correctly interpret the native required attribute and announce the field as required to users. Keeping both attributes doesn’t cause a functional problem, but it creates maintenance overhead, clutters your code, and signals to other developers that something special might be going on when it isn’t.
How to fix it
- If your element already has the required attribute, remove aria-required="true".
- If your element only has aria-required="true" and you want browser-native validation, replace it with required.
- In rare cases where you need to support assistive technologies that don’t recognize the native required attribute (some very old screen reader versions), keeping both is a conscious trade-off — but for the vast majority of projects, the native attribute alone is sufficient.
Examples
❌ Redundant aria-required alongside required
<form action="/order">
<label for="city">City</label>
<input id="city" name="city" type="text" aria-required="true" required>
<label for="email">Email</label>
<input id="email" name="email" type="email" aria-required="true" required>
<label for="comments">Comments</label>
<textarea id="comments" name="comments" aria-required="true" required></textarea>
<button type="submit">Submit</button>
</form>
This triggers the validator warning on every element where both attributes appear.
✅ Using the native required attribute only
<form action="/order">
<label for="city">City</label>
<input id="city" name="city" type="text" required>
<label for="email">Email</label>
<input id="email" name="email" type="email" required>
<label for="comments">Comments</label>
<textarea id="comments" name="comments" required></textarea>
<button type="submit">Submit</button>
</form>
✅ Using aria-required on a non-native element
There are valid use cases for aria-required — specifically when you build custom form controls that don’t use native form elements. In that scenario, aria-required is the correct choice because the native required attribute has no effect on non-form elements.
<div role="combobox" aria-required="true" aria-expanded="false" aria-labelledby="color-label">
<span id="color-label">Favorite color</span>
</div>
Here, aria-required="true" is necessary because a <div> doesn’t support the native required attribute.
When you write an attribute like maxlength="200 and accidentally omit the closing quote, everything that follows — including subsequent attribute names and their values — gets absorbed into that one attribute’s value. In this case, the validator sees the value of maxlength as 200 aria-required= (or similar), which is not a valid integer. The parser doesn’t encounter a closing " until it finds the next quotation mark further along in the tag, causing a cascade of errors.
This is a problem for several reasons:
- Broken functionality: The maxlength attribute won’t work because 200 aria-required= is not a valid number. The browser cannot determine the intended character limit.
- Lost attributes: The aria-required attribute is swallowed into the malformed maxlength value, so it never gets applied as a separate attribute. Assistive technologies like screen readers won’t know the field is required.
- Accessibility impact: Since aria-required="true" is lost, users who rely on screen readers won’t receive the information that the field is mandatory, potentially leading to form submission errors and a frustrating experience.
The root cause is almost always a missing closing quotation mark. Carefully check that every attribute value has both an opening and a closing ". This kind of typo is easy to make and easy to miss, especially in long tags with many attributes.
Examples
Incorrect — missing closing quote on maxlength
The closing " after 200 is missing, so the value of maxlength extends all the way to the next quotation mark it finds:
<input type="text" name="nome" id="nome" maxlength="200 aria-required="true">
The validator interprets maxlength as having the value 200 aria-required=, and only true ends up as the value of an unintended or malformed attribute. Nothing works as expected.
Correct — properly quoted attributes
Each attribute has its own properly matched pair of quotation marks:
<input type="text" name="nome" id="nome" maxlength="200" aria-required="true">
Here, maxlength="200" correctly limits the input to 200 characters, and aria-required="true" is a separate attribute that tells assistive technologies the field is required.
Incorrect — missing closing quote with more attributes
This issue can happen with any combination of attributes. Here, a missing quote after maxlength absorbs class and placeholder:
<input type="text" maxlength="50 class="username" placeholder="Enter name">
Correct — all quotes properly closed
<input type="text" maxlength="50" class="username" placeholder="Enter name">
Tips for avoiding this issue
- Use a code editor with syntax highlighting. Most editors color attribute values differently from attribute names. If you see an attribute name rendered in the same color as a value string, a quote is likely missing.
- Format attributes one per line on complex elements. This makes it much easier to spot mismatched quotes:
<input
type="text"
name="nome"
id="nome"
maxlength="200"
aria-required="true">
- Validate early and often. Running your HTML through the W3C validator regularly helps catch these small typos before they cause confusing bugs in production.
The aria-required attribute is a WAI-ARIA property that signals to assistive technologies (like screen readers) that a user must provide a value for a form control before the form can be submitted. According to the ARIA specification, the attribute’s value must be either "true" or "false". Any other value — such as "yes", "1", "", or a misspelling — is invalid and will produce this validation error.
Common mistakes include writing aria-required="yes", aria-required="", aria-required="required", or even aria-required="True" (note: the value is case-sensitive and must be lowercase).
Why this matters
When an invalid value is used, assistive technologies may not correctly interpret whether the field is required. This can lead to a confusing experience for users who rely on screen readers, as they may not be told that a field is mandatory before submitting a form. Using valid attribute values ensures consistent, predictable behavior across all browsers and assistive technologies.
When to use aria-required vs. required
For native HTML form elements like <input>, <select>, and <textarea>, you should use the built-in HTML required attribute. It provides both validation behavior and accessibility information out of the box, without needing ARIA.
The aria-required attribute is intended for custom (non-semantic) form controls — for example, a <div> with a role="textbox" or role="combobox". In these cases, the browser doesn’t know the element is a form control, so aria-required="true" communicates the requirement to assistive technologies.
Examples
❌ Invalid values for aria-required
<!-- "yes" is not a valid value -->
<div
role="textbox"
contenteditable
aria-labelledby="name_label"
aria-required="yes">
</div>
<!-- Empty string is not valid -->
<input type="text" aria-required="">
<!-- "required" is not valid -->
<input type="email" aria-required="required">
✅ Correct usage with aria-required
<div id="email_label">Email Address *</div>
<div
role="textbox"
contenteditable
aria-labelledby="email_label"
aria-required="true"
id="email">
</div>
✅ Explicitly marking a field as not required
<div id="notes_label">Notes (optional)</div>
<div
role="textbox"
contenteditable
aria-labelledby="notes_label"
aria-required="false"
id="notes">
</div>
✅ Preferred approach for native form elements
When using standard HTML form controls, skip aria-required and use the native required attribute instead:
<label for="email">Email Address *</label>
<input type="email" id="email" name="email" required>
<label for="country">Country *</label>
<select id="country" name="country" required>
<option value="">Select a country</option>
<option value="us">United States</option>
<option value="uk">United Kingdom</option>
</select>
The native required attribute automatically conveys the required state to assistive technologies and also triggers built-in browser validation, making it the better choice whenever a native form element is available.
In HTML, boolean attributes like required work differently from what many developers expect. Their presence on an element means the value is true, and their absence means the value is false. According to the WHATWG HTML specification, a boolean attribute’s value must either be the empty string or an ASCII case-insensitive match for the attribute’s canonical name. For the required attribute, this means the only valid values are "" (empty string) and "required".
A common mistake is writing required="true" or required="false". The value "true" is not a valid boolean attribute value in HTML and will trigger this validation error. Even more confusingly, writing required="false" does not make the input optional — since the attribute is still present, the browser still treats the field as required. This can lead to subtle bugs where a form field appears to be optional in your code but is actually enforced as required by the browser.
This matters for several reasons:
- Standards compliance: Invalid attribute values violate the HTML specification and will cause W3C validation errors.
- Code clarity: Using non-standard values like "true" or "false" misleads other developers about how the attribute works.
- Unexpected behavior: required="false" still makes the field required, which can cause confusing form behavior.
To make a field optional, simply remove the required attribute entirely rather than setting it to "false".
Examples
Incorrect: Invalid values for required
These will all trigger the “Bad value for attribute required“ validation error:
<input type="text" required="true">
<input type="email" required="false">
<input type="text" required="yes">
<input type="text" required="1">
Correct: Valid uses of the required attribute
All three of these forms are valid and make the input required:
<!-- Preferred: no value (most concise) -->
<input type="text" required>
<!-- Also valid: empty string -->
<input type="text" required="">
<!-- Also valid: canonical name as value -->
<input type="text" required="required">
Correct: Making a field optional
To make a field optional, remove the attribute entirely:
<input type="text">
Full form example
<form action="/submit" method="post">
<label for="name">Name (required):</label>
<input type="text" id="name" name="name" required>
<label for="notes">Notes (optional):</label>
<input type="text" id="notes" name="notes">
<button type="submit">Submit</button>
</form>
This same rule applies to other boolean attributes in HTML, such as disabled, checked, readonly, multiple, and autofocus. They all follow the same pattern: use the attribute with no value, with an empty string, or with the attribute’s own name as the value. Never assign "true" or "false" to them.
The aria-required attribute tells assistive technologies that a form field must be filled in before the form can be submitted. However, this attribute is only valid on elements that function as interactive widgets. A bare div has no implicit ARIA role, so assistive technologies have no context for what kind of input is expected. The validator flags this because an aria-required attribute on a generic div is effectively meaningless without additional ARIA attributes that define the element’s role and behavior.
This matters for several reasons:
- Accessibility: Screen readers and other assistive technologies rely on roles to understand how to present an element to users. Without a role, aria-required provides incomplete information.
- Standards compliance: The WAI-ARIA specification defines which attributes are allowed on which roles. Using aria-required without an established role violates these constraints.
- Browser behavior: Browsers may ignore or misinterpret ARIA attributes when they appear on elements that lack the proper role context.
How to fix it
Option 1: Use native semantic HTML (preferred)
Whenever possible, use native HTML form elements. They come with built-in accessibility semantics, keyboard interaction, and validation — no ARIA needed.
Replace a div with aria-required="true" with an appropriate form control using the native required attribute:
<input type="text" required>
<select required>
<option value="">Choose one</option>
<option value="1">Option 1</option>
</select>
<textarea required></textarea>
Option 2: Add an appropriate role attribute
When you must use a div as a custom widget (styled and enhanced with CSS and JavaScript), add the correct role attribute to give it semantic meaning. Choose the role that matches the widget’s actual behavior — don’t just pick one arbitrarily.
Common roles that support aria-required:
- combobox — a custom dropdown with text input
- listbox — a custom selection list
- radiogroup — a group of radio-like options
- spinbutton — a numeric stepper (also requires aria-valuemax, aria-valuemin, and aria-valuenow)
- textbox — a custom text input
Option 3: Add other qualifying ARIA attributes
For certain widgets like sliders or spinbuttons, you may need aria-valuemax, aria-valuemin, and aria-valuenow in addition to (or as part of) defining the role. These attributes inherently establish a widget context.
Examples
❌ Invalid: aria-required on a plain div
<div aria-required="true">
<div data-value="One">1</div>
<div data-value="Two">2</div>
<div data-value="Three">3</div>
</div>
This triggers the validation error because the div has no role or other ARIA attributes to define what kind of widget it is.
✅ Fixed: Adding the appropriate role
<div aria-required="true" role="radiogroup" aria-label="Pick a number">
<div role="radio" aria-checked="false" tabindex="0">1</div>
<div role="radio" aria-checked="false" tabindex="0">2</div>
<div role="radio" aria-checked="false" tabindex="0">3</div>
</div>
Adding role="radiogroup" gives the div a semantic identity. Note that child elements also need appropriate roles and attributes for the widget to be fully accessible.
✅ Fixed: Using native HTML instead
<fieldset>
<legend>Pick a number</legend>
<label><input type="radio" name="number" value="1" required> 1</label>
<label><input type="radio" name="number" value="2"> 2</label>
<label><input type="radio" name="number" value="3"> 3</label>
</fieldset>
This approach uses native radio buttons with the required attribute, eliminating the need for ARIA entirely. The browser handles accessibility, keyboard navigation, and form validation automatically.
✅ Fixed: A custom spinbutton with value attributes
<div role="spinbutton"
aria-required="true"
aria-valuemin="0"
aria-valuemax="100"
aria-valuenow="50"
aria-label="Quantity"
tabindex="0">
50
</div>
For a spinbutton role, you must also provide aria-valuemin, aria-valuemax, and aria-valuenow to fully describe the widget’s state.
Ready to validate your sites?
Start your free trial today.