The acronym ARIA stands for Accessible Rich Internet Applications. The purpose of ARIA is to make web content more accessible for people with disabilities. ARIA can enhance accessibility in custom-designed user interface controls and components, but incorrect use of ARIA can hinder accessibility and create a worse experience than no ARIA at all. Standard, semantic HTML components don't need ARIA to be accessible. As the saying goes, no ARIA is better than bad ARIA.
Advanced use of ARIA is a specific discipline that should be encapsulated into custom UI components that are used to create a consistent experience across an application. Creating such a reusable component library is a common practice in Angular development. Angular ESLint has rules for checking ARIA, but Angular does not add this validation out of the box. This post walks you through how to add Angular ESLint to a component library project, then dives deeper into the ARIA rules. I'll cover what each rule looks for in the Angular template code and how it uses the underlying libraries to validate ARIA roles and attributes.
Add Angular ESLint to an Angular Library Project
In the previous post I covered how to add Angular ESLint to an Angular project. This post shows how to create an Angular library project with Angular ESLint support.
To generate a new Angular workspace run the
ng new schematic without creating the default application:
ng new my-workspace --create-application false cd my-workspace
Add Angular ESLint to the workspace with the
ng add schematic:
ng add @angular-eslint/schematics
Generate an Angular library using Angular ESLint's library schematic that runs the Angular library schematic under the hood then adds support for Angular ESLint:
ng generate @angular-eslint/schematics:lib
The workspace will have both root and project level eslint configuration. The project
.eslintrc.json files extend from the root level config, so rules and their options can be set at the global level and added or overridden at the project level. Configure the ARIA template rules under "*.html" overrides:
Next let's take a deeper look at the two ARIA rules from Angular ESLint that are configured in the
Angular ESLint ARIA Rules
The Angular ESLint ARIA rules run against Angular template code both inline and in separate template files and identify incorrect usage of WAI-ARIA roles and their associated ARIA attributes. Ensuring WAI-ARIA criteria are met enables user agents and assistive technologies to gather information about and interact with web content and controls.
These rules originated from the eslint-plugin-jsx-a11y project and were ported over and implemented for Angular ESLint. Angular ESLint and eslint-plugin-jsx-a11y both use the aria-query and axobject-query libraries to query information about ARIA roles and attributes.
Rule: Valid ARIA
accessibility-valid-aria rule checks
aria-* attributes to be valid ARIA. The rule looks for HTML elements with bound or plain text ARIA attributes. Then it looks up the ARIA property definition from the aria-query library to get the ARIA attribute value type and allowed values.
If aria-query doesn’t have a definition for the matched ARIA attribute, the rule reports an invalid attribute value violation with the suggested fix to remove it:
If the ARIA attribute value is a literal value, it checks the value to be of the defined value type and one of the allowed values if provided. If the ARIA attribute value doesn’t match the ARIA property definition, the rule reports a violation that the attribute’s value is invalid:
The template parser can only check the nodes and static values in the template itself, so a dynamically bound attribute value does not get flagged as a violation:
Rule: Role Has Required ARIA
Note: You must be on at least version 14.2.0 of Angular ESLint to use the
This rule matches HTML elements with a plain text
role attribute and checks that the given role has the required ARIA attributes using the role definition from the aria-query library. For example, the switch role definition has one required property, aria-checked.
Using role mappings from the axobject-query library, it determines if the HTML element's semantic role matches the given role. The
role="switch" can be applied to an
<input type="checkbox"/> and the required
aria-checked property is covered by the element’s semantic role. A
<span> element does not have those same semantic properties and would be flagged as a violation if given the
The complete set of roles with required ARIA properties covered by the
accessibility-role-has-required-aria rule is as follows:
|WAI-ARIA role||Required ARIA|
Suggestion for Adoption
Enabling Angular ESLint's accessibility rules all at once in a codebase with existing accessibility issues can produce a long list of violations that might initially seem overwhelming and difficult to prioritize. Enable these sets of rules incrementally to tackle one category at a time:
All content and functionality must be usable with the keyboard. Keyboard access is essential for assistive technologies and should be a top priority. The article in this series on Angular ESLint Rules for Keyboard Accessibility covers the lint rules that can help. You won't be able to automate validation of all keyboard functionality with lint rules or automated testing. Be sure to incorporate manual interaction testing into your process to ensure a logical focus order is maintained along with a visible focus ring.
ARIA Roles and Attributes
Providing accessible components from a shared library helps standardize your approach to UI/UX and accessibility across your application(s). Isolate most ARIA to your custom UI components and use Angular ESLint's ARIA rules to validate best practices.
Content and Relationships
These rules ensure accessibility for non-text content and content relationships in forms and tables. Alternative text should convey the purpose and context for non-text content. Ensuring content accessibility also requires human input and manual review to make sure the content is meaningful and presented consistently. Stay tuned for my last article in this series about the Angular ESLint Accessibility Rules for Content and Relationships.
But Wait, There's More? There Sure Could Be
The eslint-plugin-jsx-a11y library, where these Angular ESLint ARIA rules originate, has even more rules for validating ARIA that could be borrowed from and added to Angular ESLint. These rule additions could also leverage aria-query and axobject-query to validate ARIA usage and encourage better practices with semantic HTML.
Even More ARIA Rules in eslint-plugin-jsx-a11y
I would also like to implement these rules for Angular ESLint:
Elements with ARIA roles must use a valid, non-abstract ARIA role.
Valid ARIA roles must be used in order for user agents to understand and interact with those elements according to specifications. Abstract roles are the foundational roles upon which other WAI-ARIA roles are built and organized and are not to be used directly.
Enforce that elements with explicit or implicit roles defined contain only
aria-*properties supported by that role.
It does no good to add ARIA attributes to elements with roles that don't support those attributes.
aria-hidden="true"is not set on focusable elements.
Using aria-hidden hides an element and its children from the accessibility API. Elements that aren't accessible to assistive technologies should not be able to receive focus via keyboard.
ARIA roles should not be used to convert an interactive element to a non-interactive element.
This rule prevents interactive elements meant as controls from being assigned non-interactive roles meant for content or containers. A content role such as meter, for example, could not be assigned to an
ARIA roles should not be used to convert a non-interactive element to an interactive element.
Elements meant for content or containers, such as
<li>, should not be assigned interactive roles meant for controls such as the button or checkbox roles.
ARIA roles should not redundantly match an element's default/implicit role already set by the browser.
<input type="checkbox">element already has the implicit role checkbox, so adding
role="checkbox"would be redundant.
Enforces using semantic DOM elements over the ARIA role property.
This rule prevents content or container elements like
<div>from being assigned roles like banner or heading where a built-in, semantic HTML element is preferable.
🎉 Shout out in the comments if you think having these rules in Angular ESLint would improve accessibility practices in your Angular codebase!
- ARIA Authoring Practices Guide on W3C Web Accessibility Initiative
- Easy Checks – A First Review of Web Accessibility on W3C Web Accessibility Initiative
- WAI-ARIA roles on MDN
- Understanding Success Criterion 4.1.2: Name, Role, Value on W3C's Understanding WCAG 2.1
- eslint-plugin-jsx-a11y on GitHub
- aria-query on GitHub
- axobject-query on GitHub
Latest comments (1)
Great article!! Thanks for sharing!! :D