a11y/invalid-aria-value · Invalid ARIA attribute value
An aria-* attribute's value should match the type the WAI-ARIA spec defines for it.
Severity: warning · Category: a11y
What it checks
Flags a literal aria-* attribute whose value does not match the type the WAI-ARIA spec defines for that attribute.
Only attributes the spec defines are checked here. An unrecognized name is a11y/unknown-aria-attribute’s concern, not this rule’s. Each spec type is validated differently:
- boolean (e.g.
aria-hidden) must betrueorfalse. - tristate (e.g.
aria-checked) must betrue,false, ormixed. - token (e.g.
aria-live) must be one of the attribute’s fixed set of values. - tokenlist (e.g.
aria-relevant) takes one or more whitespace-separated words, each from the fixed set; an empty value is invalid. - integer (e.g.
aria-colcount) must be a whole number. - number (e.g.
aria-valuenow) must be a finite number. - string, id and idlist (e.g.
aria-label,aria-activedescendant) accept any literal; these can’t be checked statically.
Two deliberate divergences from the letter of the ARIA spec, both to match the Svelte compiler you build with. The spec lists undefined as a value for several boolean attributes, and says a zero-length string should be treated as an absent attribute; the compiler rejects both (a11y_incorrect_aria_attribute_type_boolean), and so does this rule. A rule that disagreed with your own build would be noise, not a second opinion.
Attribute and role names are matched case-insensitively, since HTML lowercases them: ARIA-LABLE is reported as aria-lable, exactly as the compiler reports it.
Not flagged:
aria-hidden="true", a valid boolean.aria-live="polite", a valid token.- An expression-valued attribute, since its runtime value is unknown statically:
aria-hidden={isHidden}. - An unrecognized attribute name, e.g.
aria-bogus="x", whicha11y/unknown-aria-attributeowns.
Why it matters
Assistive technology expects each aria-* attribute’s value to match its spec-defined type. aria-hidden="yes" isn’t a recognized boolean, and aria-live="loud" isn’t one of the fixed live-region tokens. Both are ignored or misread, so the state or region the author intended to expose never reaches the user, with no visual sign anything is wrong.
How to fix
Use a value matching the attribute’s WAI-ARIA type: aria-hidden="true" for a boolean, aria-live="polite" for a token:
<div aria-hidden="true"></div>
Mode differences
None. This rule reads source, the same .svelte and .ts files, everywhere it runs. The CLI, the Vite plugin’s build pass, and the live dashboard’s static baseline all report it identically, and the rendered-HTML pass never re-evaluates it. Scoping a run with --route skips it: component-scoped rules have no route to attribute a finding to.
Disabling
If a value is intentionally non-standard, silence a single element with <!-- svelte-vitals-disable-next-line a11y/invalid-aria-value -->, or turn the rule off:
export default {
rules: {
'a11y/invalid-aria-value': 'off'
}
};