Specs are usually not very fun, but I have learned that reading the ARIA specs is important to fully understand all the various options that are available. In this presentation, I will walk you through the ARIA spec and show you how to make the most out of it to create custom components with ARIA.
- TechAccess Oklahoma 2022 Registration
NOTE: Slides are about 500mb so may take a while to download and start.
Hello TechAccess Oklahoma! Welcome to ARIA Spec for the Uninitiated! I know you could have chosen to be anywhere else at this time, so I am grateful you chose to be here for this presentation.
This presentation is mostly for new users of ARIA, I am basically going to be walking through documentation and showing a few examples, but even if you have been using ARIA for a while, you might learn a few things.
Here is my agenda for today.
I'll start off first with a warning about the Dangers of ARIA.
From there I'll do an introduction of the official ARIA standard, pointing out important sections and then I'll get into the 5 rules of ARIA.
That last important resource I'll go over is ARIA authoring practices, and I want to discuss their purpose and proper use.
At that point, you should be pretty well introduced to ARIA and better equipped to create custom components.
So I want to first talk about the dangers of ARIA and why it is important to know and use it right. ARIA is very powerful, and essential to providing the level of dynamics available in todays web. Using ARIA incorrectly can cause some serious barriers for users of assistive technologies. ARIA should be a last resort, a way to fill in the gaps that HTML has.
So why is ARIA so troublesome? Well, besides people not taking the time to learn it properly, I would say one main reason is because ARIA support varies. There are a lot of hands in the pot by the time it reaches an assistive technology user.
Unfortunately, ARIA is not always completely supported by both browsers and assistive technologies the same way, and with the ARIA that is supported, sometimes there are bugs in the implementation. What's frustrating is that it is different across all browser and assistive technology combinations, something may work great in one combination, but not be implemented or function properly in another. Sometimes, the implementations may break after originally working properly. It is the same as you would expect with any of the other web technologies. Unfortunately, there are no media queries that you can query for support like with CSS, or the ability to test for support with JS to provide a polyfill. The only thing you can do is test your work and provide workarounds. But you have to know what you are doing. Throwing ARIA at a problem is not always the solution.
To prove that point, a survey of 1 million home pages by WebAIM in February of 2021, home pages with ARIA present averaged 41% more errors than pages without ARIA (WebAIM Million 2021). The more that ARIA is used, the more errors were found on the page. So, not only is throwing ARIA at a problem not a proper solution, it could be making things worse.
ARIA should only be used when necessary, to fill in gaps that HTML does not provide. This why there is a very popular sentiment in the community that No ARIA is better than bad ARIA. The point here is that if you don't know how to really use ARIA, it's just better to leave it off. Thankfully, you are here today, and hopefully you will learn enough to not contribute to making things worst.
So, if ARIA is so dangerous, why am I here talking to you about it? I personally think that ARIA has a bad rap, and that might be a controversial statement to some, but I think its excessively vilified, and I can certainly understand why; a lot of the negative sentiment is definitely warranted, I will not deny that. It can easily be misunderstood and abused, and can do some serious damage to an assistive technology users experience. I think it's just much easier to say "Don't use it" than it is to properly explain it and learn it, but that's not going to help anyone. At a certain point, HTML alone is not enough and you will need to reach for ARIA. Just like anything else, it's not perfect by any means, but you shouldn't be overly afraid of it, and you shouldn't avoid it. You definitely need to respect ARIA, I recommend you take the time to learn and understand it.
With that being said, let's get into the documentation.
This is the very first resource I want to expose you to, the official ARIA standard. Normally, visiting the official standard or spec for any kind of web technology is reserved for the extremely academic types. Most of You have probably never read the official ecmascript standard, but I want you to treat the official ARIA standard as an API guide to get the most up to date information on available options. If you want to know what something means, I urge you to come here first.
You can always get to the latest version of the standard by going to www.w3.org/TR/wai-aria, which I have on the screen now The first thing you will learn here is that ARIA actually stands for Accessible Rich Internet Applications.
As of today, the latest version of the ARIA standard is 1.1. Make sure to bookmark this. If you want to do ARIA right, you will reference this a lot!
I don't expect you to the read the whole thing, but there are a couple of sections that I want to point out to you right now that will serve as the basis for everything you will do related to ARIA from now on.
The first section I want to point out on the screen now is section 5.3, The Categorization of Roles. This section lists the available roles that ARIA provides. What are roles? Well, roles are how you provide semantics to elements, semantics are extremely important to accessibility.
So what exactly are semantics? Semantics basically express what something is. Once you know what something is, you then know how to use it, and what the expected result will be. For example, if I hand you an object and tell you it is a fork, you will most likely know what it is and how it is to be used.
ARIA roles provide semantics and The ARIA 1.1 standard provides 70 usable roles. That's the total list. You cannot make up your own roles. Let me repeat that, you cannot make up your own role.
So of these 70 roles in version 1.1, only 29 of them are interactive widget roles, and I am going to focus on those right now.
These interactive roles are defined in section 5.3.2, Widget Roles and can be broken down into 2 groups, stand-alone and composite.
First, stand-alone widgets either operate on their own or exist to be part of a composite widget. There are 20 stand-alone widget roles that I am highlighting on the screen now, some of which may be familiar to you already like button, checkbox, or link. Again, when it comes to stand-alone widget roles, this is the complete set. You cannot make up your own.
The next group are composite widget roles, and these are essentially parent roles, or containers for other stand-alone widget roles. There is a very strict hierarchy when it comes to composite widgets, these have to be composed with very specific stand-alone roles and often in a very particular order. In most cases you cannot pick and choose which roles you use to compose a widget, since some stand-alone roles can only exist as a child, or nested, in one of these 9 composite widget roles, highlighted on the screen.
Let me repeat that, there a very strict parent-child relationships between certain roles, so some roles can only be used as a child of a specific composite role. This is extremely important to understand, especially with how easy certain UI libraries make it to reuse components and render wherever necessary. Be very careful about how you nest components and roles, because you can be breaking you're well intended accessibility if you don't respect the parent-child relationship of roles.
Detailed information on how to use roles and how to apply stand-alone vs composite roles can be found in the definitions for each role.
Diving into the definition for roles, they all follow the same format. On the screen now, I am going to use the button role definition as an example.
Each role provides a definition and information on usage. In this case for example, a button is defined as "An input that allows for user-triggered actions when clicked or pressed." In addition to the description, helpful usage guidelines are also included. For button, this is information I am highlighting describes how buttons support aria-pressed issued to create toggle buttons. Take the time to read this information because it always provides additional information that may not be gleaned from the general template for definitions.
After the definition, each role will have a table of characteristics that will further help you in determining what you need to include, or what is supported, when using a particular role.
The first section to point out is the Base Concept section. Not all roles will have this, but this is your first clue that the semantics provided by this role can be provided by an equivalent HTML element. For the ARIA role of button, the base concept is an HTML button. When you see this, I highly recommend that you move onto using the HTML equivalent that is listed here instead of the the ARIA role.
After the Base Concept is the finite list of supported and inherited states and properties. I'll go over states and properties in a little bit, but the important thing to remember here is that these are the only states and properties that can be used on this role. For button, there are only 2 explicitly supported states, aria-expanded and aria-pressed.
After the explicit list of Supported States and Properties, is the Inherited States and Properties. These are also supported by the role but they are, as described, inherited from a superclass role.
This collection of supported and inherited states and properties are the only states and properties that this role supports. If you apply a state or property that is not on this list of supported states and properties, you are breaking accessibility.
The next set of information has to do with the accessible name, letting you know if an accessible name is required and where that accessible name is calculated from. Accessible names, for interactive controls especially, are extremely important because they identify a widget. This is how assistive technology users know what they are interacting with. In the case of a button, the accessible name comes from the contents of the button.
Speaking of the contents, pay attention to the last item here children presentational. This is another clue to let you know what you are allowed to nest inside the element. If this is TRUE, it basically means that the contents inside will be stripped of any semantics. So if you nesting links inside of buttons, or headings like I recently did, you are breaking accessibility.
Now, a few more important sections I want to point out, related to specific to composite roles. If you remember, when talking about composite roles, I told you that composite roles have a very specific parent-child hierarchy. The role definitions give you this information, and it's listed in the Required Owned Elements section of the characteristics table. Essentially, these are the required child role elements for this role.
Not all roles have this section, in this case I am displaying the menu role definition. The Required Own Elements here let you know that the menu role will require at least one instance of an element with one of these roles. Again, these are the children that will be expected for this role. If you are missing any of the elements listed in the Required Owned elements, you are breaking accessibility.
On the flipside, you also get information on the required parent role for a particular element, and this is documented in the Required Context Role section in the table of characteristics.
One the screen I am showing the menuitem role definition as an example, and the required parent role for menuitum is one of group, menu, or menubar. If you are using the menuitem role and it is not nested in one of these roles, you are breaking accessibility.
So that is a very high level overview of how the spec defines roles, and how you can use this information when specifying roles for your ARIA components.
One thing I want to make you aware of when using roles.
Roles do not provide interaction. They simply just describe what something is, but do not provide the expected behavior.
And once you tell someone what something is, they will know how to use it. YOU need to provide the expected interaction. It's important to know that certain roles can change input modes for various assistive technologies, so specific interactions are expected. For example, a specific role may change what is expected of the arrow keys, and you need to provide that. When you don't provide those interactions then you are breaking the contract established by the role.
Along with providing semantics by way of Roles, ARIA also provides states and properties to further describe interfaces to assistive technologies.
And as of ARIA 1.1, there are a total of 48 states and properties.
So Let's take a look at available states and properties.
Back to the official ARIA standard, at section 6.6 which is the Definitions of States and Properties. All the available states and properties, with their available values are listed here. Just like the roles, you cannot make up your own states and properties, or provide your own values. You can only use these 48. Again, you cannot make up your own states and properties.
Along with not being able to make up your own, there are rules about which states and properties you can apply to specific roles. Some states and properties are required on certain roles, and some states and properties are not supported or allowed on other roles.
Looking at aria-expanded as an example of definitions for a state or property, you'll see that the format is the same as role definitions. It's starts off with a description and some usage guidelines.
Just like roles, each state and property definition includes a table of characteristics. Here in the Used in Roles section, we see all the roles that support this particular state. As confirmation, I see that button is listed. That matches the supported states we saw for button earlier. So if you use this state on a role that is not listed here, then you are breaking accessibility.
After the characteristics table, you have a table documenting the available values for this state. For example, aria-expanded accepts a true or false value, where true means it is expanded and false means it is collapsed. These are the only values that you can use for this state. If you use something other than the values listed here, you are breaking accessibility.
So, understanding roles, states, and properties, understanding the relationships between them, knowing when and where to apply them is everything for proper ARIA usage What I have shown you here is how to use the specs when creating your custom components.
Again, this documentation is replete with everything you need to understand how things work together. That's a big part of understanding ARIA, but there are still a few more resources I want to go over that will complete your initiation into ARIA.
When it comes to ARIA, there are 5 very well established rules that you need to be aware of. These high-level rules will always guide you in making the right decision when you are developing you own ARIA widgets.
The first rule of ARIA might as well be the only rule of ARIA because it is repeated so often. If you have already started on your journey in ARIA, you may have heard this one already. The first rule is DON'T USE ARIA. Now, this may remind of a sort of fight club rule, and ARIA can be the cause of a lot of fights, but if you are confused by this rule its because it is not totally accurate.
This is actually an incomplete rule. The entire rule is Dont use ARIA IF you can use HTML instead. The 2nd part is almost always left off, but it is really important. As I mentioned in the overview of the ARIA standard, ARIA is used to describe widget role semantics and state. A lot of this is covered by by existing HTML elements and properties.
So, instead of role=banner you should use the header tag.
Instead of role="complementary" use the aside tag.
role="form" is the same as the form tag.
role="main" is the same as the main tag.
role="navigation" is the same as the nav tag.
role="region" is the same as the section tag with an accessible name. Without an accessible name, the section tag by itself is not recognized. We'll talk more about what accessible names are with the 5th rule of aria.
role="contentinfo" is the same as the footer tag.
Now, the search landmark role does not have a corresponding HTML element.
As I mentioned earlier, if there is an HTML equivalent to an ARIA role, you should always prioritize using HTML.
And if you can use the HTML counterpart first, AND it is supported by browsers and assistive technologies, then you are better off using just the HTML as it will provide all the same properties as ARIA, while providing a more stable experience.
Simply by using the right HTML element, you get semantics, the focusability, and interaction already built in. It's less work for you, less code, and less of a surface area for bugs in the experience.
This is exactly why accessibility professionals stress learning HTML so much. It does a lot of the heavy lifting for you.
And I know it's easier than it sounds, since there are a lot of HTML elements to choose from. It can be hard to know when to use HTML vs ARIA, so I am currently working on a periodic table of semantics.
This periodic table of semantics lists every HTML element available, and matches it to an ARIA role. So if you need to provide semantics, you can easily find out if there is an HTML element you can use, and if it's not you can fill in the gap using ARIA. I am still working on this, but the data is all there with links to each of the official specs. You can find this periodic table of semantics at http://bit.ly/2IMK1ko.
The 2nd rule of ARIA is don't change native semantics. If you are being a responsible and using HTML first, you have to make sure that you don't use ARIA to replace the semantics that the native element has. You see, when you use an ARIA role, your are explicitly setting the semantics of that element. The ARIA role takes precedence over the HTML. Let me show you an example.
Let's say your site or application has a collapsed menu, and you are using a link because its easy to style, and it also natively provides focusability, which you heard was good for accessibility. You provide a handler to event to prevent the default behavior of making the page jump when this link is used, and then display your menu. At some point you learn that links are meant for navigation and you should really use a button for this, but you don't want to have to modify your markup or CSS. You also just learned about ARIA roles and how they provide semantics so you decided to add the role of button.
Now, this menu is communicated as a button and you are happy!
At this point, considering all the work you had to do, hopefully you realized that it would have been easier to just use a button. Again, If you use HTML as intended, the platform will provide a lot for you including semantics and interaction. You then use ARIA to fill in the gaps as necessary.
Hopefully, the 3rd rule of ARIA should should be familiar to you already. Basically, all interactive ARIA roles need to be operable by keyboard. If functionality is provided via a mouse, touch or any other method of input, it also needs to be available by keyboard. This is important in fulfilling the contract of semantics, keyboard support is absolutely fundamental for accessibility support. Ensuring keyboard support will get you a long way with other input modalities as well, like game controllers for example.
The 4th rule of ARIA is don't use role="presentation" or aria-hidden="true" on visible focusable elements.
The role of presentation is a very special role, it basically removes the semantics of an element. If you do this to an interactive, or focusable element, then an assistive technology user will not know what it is or how to use. This could create a serious barrier.
Aria-hidden is an aria state that effectively hides that element from assistive technology users. ARIA just describes things, it does not affect appearance or functionality the way HTML attributes might. When you use aria-hidden="true" on an element, its still rendered and visible on the screen. Doing this on a visible interactive element hides that element, which can again create a serious barrier to your users.
Proper ways to hide elements is a separate conversation, but for now just now that role="presentation" and aria-hidden="true" can be very dangerous if not fully understood and used properly.
The fifth and last rule of ARIA is that all interactive elements must have have an accessible name. Why is this important?
Well, If semantics or role gives you the type, then the accessible name tells you what. And not only is it important for screen reader and braille users, it's also important for voice recognition users to be able to identify and and interact with controls on a page. So, make sure that all interactive elements have an accessible name.
The 5 rules of ARIA are documented here on the w3 site at https://www.w3.org/TR/aria-in-HTML. You can read up on more information and examples.
There is some other really good information documented on this page. I encourage you to check it out to learn more.
Up this point, I've gone over a lot of documentation and principles. Now it's time to get into some examples of implementing ARIA.
When it comes to creating custom components, you don't always have to start from scratch. There are some established examples you can use to start off with.
Another important resource that I want to discuss are the official ARIA authoring practices. This resource is often referred to as an example of proper ARIA implementation for various widgets.
The authoring practices are available at https://www.w3.org/TR/wai-aria-practices, and they demonstrate about 27 different widgets and patterns. Some are essentially ARA recreations of HTML elements, like button and checkbox, but some of them are interactive widgets only available via aria, like Tabs.
I am going to use the Accordion example, because I actually wrote the sample code for this pattern so I am most familiar with it.
Now each pattern starts off with some information about general purpose and usage, which can include variations on the pattern.
I am going to skip over the example right now, and go over the keyboard interaction section. Included with each pattern is the expected keyboard interaction which describes each interactive element, with the expected keys to implement and the expected result of activating those keys. For example, with the Accordion, when focus is on an accordion header, ENTER or SPACE should essentially toggle whether or not the accordion is expanded. Expectations for TAB and SHIFT+TAB, as well as optional controls like UP or DOWN arrows, and HOME or END are also included.
After the keyboard support section, is a section that lists all the necessary ARIA roles, states, and properties for the pattern. Everything you need to know in terms or implementing this pattern is listed here.
Now, to experience this is in real life, lets go back to the accordion example that is provided here.
All of the examples follow the same outline. They start off with some links at the top, a brief introduction on the example being demonstrated, and how the pattern is being implemented. I'll get back to these links in a bit.
After that is a live, working implementation of the pattern that you can play with and test.
After the example, is usually a description or explanation of various accessibility features that are implemented. While not always specific to ARIA, it's general good guidance to follow. This guidance here explains the focus indication, and how it helps let users know that enhanced keyboard navigation is provided.
Following that is the Keyboard Support that is implemented, and again this breaks down all the expected keys that are implemented and the expected interactions.
And then a more detailed description of the roles, states, properties, and tabindex used in the pattern. This is like a mapping of HTML elements to ARIA roles and attributes used in the example.
So, maybe you are thinking about skipping the rest of this presentation and just copying the examples here, since everything is done already. Well, not so fast. These authoring practices are often used in way that they were not originally intended, and often used incorrectly. Let me point out some important notices in the documentation.
In the very beginning, I talked about these links at the top and I want to point out some things mentioned in the Browser and Assistive Technology support page.
"Testing assistive technology interoperability is essential before using code from this guide in production Because the purpose of this guide is to illustrate appropriate use of ARIA 1.1 as defined in the ARIA specification, the design patterns, reference examples, and sample code..."
"...intentionally do not describe and implement coding techniques for working around problems caused by gaps in support for ARIA 1.1 in browsers and assistive technologies."
"It is thus advisable to test implementations thoroughly with each browser and assistive technology combination that is relevant within a target audience."
It goes on to say "Except in cases where the ARIA Working Group and other contributors have overlooked an error, examples in this guide that do not function well in a particular browser or with a specific assistive technology..."
"...are demonstrating browser or assistive technology bugs. Browser and assistive technology developers can thus utilize code in this guide to help assess the quality of their support for ARIA 1.1." that is from the ARIA authoring practices document, section 2.2 Browser and Assistive Technology support, with some added emphasis by me. So what does that mean?
What this is saying is that they don't provide any guidance as to how to work around bugs in browsers or AT, and these guides provide the state at which they would like things to be supported. It's a testing tool basically for browsers and AT vendors to help beef up support if something is not working. The truth of the matter is that ARIA is only spec. There is no guarantee that browser vendors and assistive technologies are going to support all the roles, states, and properties. Just the same way building codes do not always guarantee that something is built properly and to code. Because of this, they advise testing everything before using. One more note I want to point out here.
"Currently, this guide does not indicate which examples are compatible with mobile browsers or touch interfaces. While some of the examples include specific features that enhance mobile and touch support,"
"...some ARIA features are not supported in any mobile browser. In addition, there is not yet a standardized approach for providing touch interactions that work across mobile browsers." and that is from the ARIA authoring practices document, section 2.3 Mobile and touch support.
This is basically an acknowledgement that these patterns, and the ARIA used to build them, may not be supported by mobile browsers. In fact, the design patterns do not even really take mobile and touch into consideration. This is future work to be done.
I see a lot of component libraries advertise that they are accessible because they implement the ARIA authoring practices, just be aware that it doesn't always guarantee accessibility. Things need to be tested.
So what do you do? I am not telling you that you can't use these patterns. You can certainly use them as a basis for your widgets, but you shouldn't use them as is. The point to all of this is
Test! Test! Test! Everything that you do. And not just on your own, hopefully with real users. You will discover some inconsistencies, and you will be expected to fill in those gaps on your own. That is why it is important to know and understand ARIA, and not just copy/paste these patterns.
The ARIA SPEC calls this out explicitly in the Testing Practices and Tools section by saying/
The accessibility of interactive content cannot be confirmed by static checks alone. Developers of interactive content should test for device-independent access to widgets and applications, and should verify accessibility API access to all content and changes during user interaction. from the ARIA authoring practices document, section 1.5.2 Testing Practices and Tools.
So just another prompt to make sure that you are actually testing with assistive technologies, and not just relying on the inclusion of ARIA to ensure accessibility.
Another thing I want to mention is that since this is basically an ARIA test bed, a lot of times they will excessively use ARIA roles and properties that are perfectly available via HTML. This is not a suggestion to use always use ARIA instead of HTML, but in order to test ARIA, they have to use all ARIA.
Again, I am not saying that you shouldn't use this resource, I am just emphasizing that you need to test everything yourself. You should definitely follow the keyboard interaction, and start with the roles and properties demonstrated, but experiment with falling back to using HTML first and then make sure you test everything with assistive technologies.
So in summary.
ARIA is dangerous if you don't know what you are doing. Remember, no ARIA is better than bad ARIA but at least now you know how to use the spec to understand how everything works together.
ARIA is finite. There are only 70 roles and 48 states and properties. You can not make up your own. There are are also strict rules around parent child relationships for roles. Again, use the standard to understand relationships.
ARIA only describes content, via roles and states or properties. It does not magically add functionality, that is up to you. Keep in mind that adding a ARIA roles may change assistive technology input modes, and usage of certain keys will be expected. You need to provide the interaction.
That's why it's best to LEARN HTML and prioritize it whenever possible. Using HTML over aria will almost always give you a more reliable experience.
I also showed you the ARIA Authoring Practices with a caveat they are not meant to be copy/pasted. They primary purpose of those examples are to provide a test bed to browser and assistive technology vendors to provide better ARIA support. They are still a good reference as a start, not an end. Ultimately, you need to TEST everything for proper support and functionality.
Don't be afraid of ARIA. Familiarize yourself with the specs, learn how to use them properly, use only what is needed to fill in HTML gaps. Mastering ARIA is not just about how to use it, but more importantly when NOT to use it.
At this point, you can consider yourself initiated but this is only the beginning. I highly suggest your continue your ARIA journey by sticking around for the next presentation by the incomparable Nicolas Steenhout who will be doing a deeper dive into ARIA. You don't want to miss it!
Before I go, I wanted to take this opportunity to quickly let you know that I do have some accessibility courses available on the Pluralsight Learning Platform, which are part of the developing websites for accessibility path.
- Meeting Web Accessibility Guidelines
- Introduction to Develop Custom Components with ARIA
- Accessibility: Testing and Screen Reader Use
If you are interested in learning more from me, you can check these out over at Pluralsight.
And with that, I say thank you for attending and thank you to Web Directions for allowing me to speak to you today. I hope you can feel more comfortable about ARIA. Again, the slides are at http://bit.ly/2Zc6TDf, and if you have an questions, comments, or feedback, you can reach me @gerardkcohen on Twitter.
Have a great rest of the day!