About This HTML Issue
The span element is a generic inline container with no inherent semantics. On its own, it carries no meaning for assistive technologies. When you add ARIA attributes like aria-expanded or aria-valuenow to a span, you are signaling that the element represents an interactive widget — but the validator (and assistive technologies) need more context. Many ARIA attributes are only permitted on elements that have certain roles, and some roles require a specific set of attributes to function correctly.
For example, aria-valuenow is designed for range widgets like sliders and progress bars. According to the WAI-ARIA specification, if you use aria-valuenow, the element must also have aria-valuemin, aria-valuemax, and a role such as progressbar, slider, meter, or scrollbar. Similarly, aria-expanded is meant for elements with roles like button, combobox, link, or treeitem. Placing these attributes on a bare span without the corresponding role violates the ARIA rules and triggers this validation error.
This matters for several reasons:
-
Accessibility: Screen readers rely on the
roleto determine how to present a widget to users. Without it, ARIA state attributes become meaningless or confusing. - Standards compliance: The HTML specification integrates ARIA rules, and validators enforce that ARIA attributes are used in valid combinations.
-
Browser behavior: Browsers use the
roleto build the accessibility tree. Aspanwitharia-valuenowbut norolemay be ignored or misrepresented to assistive technology users.
How to fix it
-
Add the correct
roleto thespan, along with all attributes required by that role. -
Use a semantic HTML element instead of a
spanwhen one exists (e.g.,<progress>or<button>). -
Remove unnecessary ARIA attributes if the
spanis purely decorative or the attributes were added by mistake.
If your span is purely visual (e.g., a decorative asterisk for required fields), don’t add state-related ARIA attributes to it. Instead, use aria-hidden="true" to hide it from assistive technologies, and place ARIA attributes on the actual form control.
Examples
Incorrect: aria-expanded on a span without a role
<span aria-expanded="false">Menu</span>
The validator reports the missing role because aria-expanded isn’t valid on a generic span.
Correct: Add a role (or use a button)
<span role="button" tabindex="0" aria-expanded="false">Menu</span>
Or, better yet, use a real button element:
<button aria-expanded="false">Menu</button>
Incorrect: aria-valuenow without the full set of range attributes and role
<span class="progress-indicator" aria-valuenow="50">50%</span>
Correct: Include the role and all required range attributes
<span role="progressbar" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100">
50%
</span>
Or use the native <progress> element, which has built-in semantics:
<progress value="50" max="100">50%</progress>
Incorrect: aria-required on a decorative span
<label for="email">
Email
<span class="required" aria-required="true">*</span>
</label>
<input id="email" name="email" type="email">
The aria-required attribute belongs on the form control, not on the decorative asterisk.
Correct: Hide the decorative indicator and mark the input as required
<label for="email">
Email
<span class="required" aria-hidden="true">*</span>
</label>
<input id="email" name="email" type="email" aria-required="true">
If you also want screen readers to announce “required” as part of the label text, add visually hidden text:
<label for="email">
Email
<span aria-hidden="true">*</span>
<span class="visually-hidden">required</span>
</label>
<input id="email" name="email" type="email" required>
The key takeaway: whenever you use ARIA state or property attributes on a span, make sure the element also has the correct role and all companion attributes required by that role. When a native HTML element already provides the semantics you need — such as <button>, <progress>, or <meter> — prefer it over a span with ARIA, as native elements are more robust and require less additional markup.
Find issues like this automatically
Rocket Validator scans thousands of pages in seconds, detecting HTML issues across your entire site.