Skip to main content

wai-aria

Warn if the role attribute and aria-* attributes don't set in accordance with specs that are WAI-ARIA, DPub-ARIA (Digital Publishing WAI-ARIA Module), and ARIA in HTML.

Warn if:

  • Clear-cut violation.
    • Use the role that doesn't exist in the spec.
    • Use the abstract role.
    • Use the property/state that doesn't belong to a set role (or an implicit role).
    • Use an invalid value of the property/state.
    • Use the not permitted role according to ARIA in HTML.
    • Don't set the required property/state.
    • The role doesn't have the required child roles (e.g., table requires row).
    • The role is placed outside its required parent context (e.g., tab without a tablist ancestor).
  • Unrecommended.
    • Set the deprecated role.
    • Set the deprecated property/state.
    • Set the implicit role explicitly according to ARIA in HTML.
    • Set the property/state explicitly when its element has semantic HTML attribute equivalent to it according to ARIA in HTML.
  • Preference
    • Set the default value of the property/state explicitly.
  • Optional checks (disabled by default)
    • Set ARIA attributes on descendants of roles whose children are presentational.
    • Use focusable interactive elements hidden via aria-hidden.

❌ Examples of incorrect code for this rule

<div role="landmark" aria-busy="busy">
<ul>
<li role="button">an item</li>
</ul>
<button aria-checked="true">Click me!</button>
</div>

✅ Examples of correct code for this rule

<div role="banner" aria-busy="true">
<ul>
<li role="menuitemcheckbox">an item</li>
</ul>
<button aria-pressed="true">Click me!</button>
</div>

Interface

{
"wai-aria": boolean
}

Options

{
"wai-aria": {
"options": {
"checkingValue"?: boolean
"checkingAllowedAccessibilityChildRoles"?: boolean
"checkingRequiredOwnedElements"?: boolean
"checkingRequiredAccessibilityParentRole"?: boolean
"checkingDeprecatedRole"?: boolean
"checkingDeprecatedProps"?: boolean
"permittedAriaRoles"?: boolean
"disallowSetImplicitRole"?: boolean
"disallowSetImplicitProps"?: boolean
"checkingPresentationalChildren"?: boolean
"checkingInteractionInHidden"?: boolean
"disallowDefaultValue"?: boolean
"version"?: "1.1" | "1.2" | "1.3"
}
}
}
PropertyTypeDefault ValueDescription
checkingValueboolean"true"Warn if use an invalid value of the property/state. You can temporarily disable this option if the WAI-ARIA spec update rather than markuplint add new value to the allowed list ahead. Don't recommend disabling basically.
checkingAllowedAccessibilityChildRolesboolean"true"Verify that roles with "Allowed Accessibility Child Roles" (called "Required Owned Elements" in ARIA 1.2) contain the expected child roles.
checkingRequiredOwnedElementsboolean"true"Deprecated: Use checkingAllowedAccessibilityChildRoles instead. Both must be true for the check to run.
checkingRequiredAccessibilityParentRoleboolean"true"Verify that roles with "Required Accessibility Parent Role" (called "Required Context Role" in ARIA 1.2) are placed in a valid parent context.
checkingDeprecatedRoleboolean"true"Warn if use deprecated role. You can temporarily disable this not to evaluate WAI-ARIA old version. Don't recommend disabling basically.
checkingDeprecatedPropsboolean"true"Warn if use deprecated property/state. You can temporarily disable this not to evaluate WAI-ARIA old version. Don't recommend disabling basically.
permittedAriaRolesboolean"true"Warn if use the not permitted role according to ARIA in HTML. This is based on the spec ARIA in HTML and is not strictly the spec WAI-ARIA, so it is an option.
disallowSetImplicitRoleboolean"true"Disallow set the implicit role explicitly. This is based on the spec ARIA in HTML and is not strictly the spec WAI-ARIA, so it is an option.
disallowSetImplicitPropsboolean"true"Disallow set the implicit property/state explicitly. This is based on the spec ARIA in HTML and is not strictly the spec WAI-ARIA, so it is an option.
checkingPresentationalChildrenboolean"false"Warn when ARIA attributes are set on descendants of roles with childrenPresentational.
checkingInteractionInHiddenboolean"false"Warn about focusable interactive elements hidden via aria-hidden.
disallowDefaultValueboolean"false"Disallow set the default value of the property/state explicitly.
version"1.1" | "1.2" | "1.3""1.3"Choose the version of WAI-ARIA to evaluate.

Default Severity

error

Options

checkingRequiredAccessibilityParentRole

Type: boolean (default: true)

Verifies that an element with an explicit role attribute is placed within the correct parent context as defined by the ARIA specification ("Required Accessibility Parent Role" in ARIA 1.3 / "Required Context Role" in ARIA 1.2).

For example, a tab role requires a tablist ancestor, and an option role requires a listbox ancestor.

When set to false, this check is disabled.

{
"rules": {
"wai-aria": {
"options": {
"checkingRequiredAccessibilityParentRole": false
}
}
}
}

[!NOTE] Only explicit roles (set via the role attribute) are checked. Implicit roles are skipped because native HTML parent-child semantics are already guaranteed by the HTML specification.

Known Limitations

  • aria-owns is not considered. The parent context check only walks the DOM parentElement chain. Elements referenced by aria-owns on a remote ancestor are not treated as accessibility children of that ancestor.
  • Shadow DOM boundaries are not crossed. The parent context check only traverses the light DOM tree. Shadow DOM host boundaries are not considered.
  • Dual violation reporting. When a role's required parent context is not satisfied, both checkingRequiredAccessibilityParentRole (child-side) and checkingAllowedAccessibilityChildRoles (parent-side) may report violations for the same structural issue. Disable one of the options if you want to avoid duplicate reports. Generally, keeping the child-side check (checkingRequiredAccessibilityParentRole) is recommended, as it reports the violation on the element that needs to be moved.

Configuration Example

Explains an example of when changes configs are necessary due to browser support status or the behavior of assistive technologies.

Below is an example of disabling disallowSetImplicitRole when the img element loading SVG requires role="img" in Safari and VoiceOver environments. (This matter is based on the issue.)

{
"rules": {
"wai-aria": true
},
"nodeRules": [
{
"selector": "img[src$=.svg]",
"rules": {
// Allows the implicit role:
"wai-aria": {
"options": {
"disallowSetImplicitRole": false
}
},
// Change to require to specify role attributes:
"required-attr": "role",
// Allow only img value for the role attribute:
"invalid-attr": {
"options": {
"allowAttrs": [
{
"name": "role",
"value": {
"enum": ["img"]
}
}
]
}
}
}
}
]
}

The selector img[src$=.svg] limits the rule to the element that is loading an SVG image. Then, disabling the disallowSetImplicitRole option allows setting role="img" which is the implicit role of the img element. Furthermore, Change to require to specify the role attribute through the required-attr rule, and allows only the img value for the role attribute through the invalid-attr rule. Doing this will urge add role="img" to the img[src$=.svg] element.