Introduction to ARIA
Transcript
Jack Auses: Hey everybody, thanks for inviting us to your meeting to talk about an introduction to ARIA and web accessibility. In this presentation– for the first five minutes or so, we’ll go over a quick overview of ARIA. What it is, some basic rules around when to use it, and its three core components.
We’ll then spend about 35, 40 minutes we’ll see going through a few examples of using ARIA to improve accessibility, such as defining landmarks on a web page, announce some dynamic content updates, labeling and describing elements, and then finally, a more complex example showing techniques for making a custom tab widget accessible.
Please, if you have any questions, pop them in the chat, and we’ll address them at the end of the session. Thalia will be monitoring that and she’ll be able to moderate any questions that come up.
So as you all know, my name is Jack Auses. I’m an Accessible Web Technology Specialist at the UChicago Center for Digital Accessibility, and we’re just going to get right into it.
[What is ARIA?]
So what is ARIA? ARIA stands for Accessible Rich Internet Applications, and it is an accessibility-enhancing suite of web standards. When written semantically, much of HTML, it is already accessible. However, HTML and JavaScript and CSS do not natively include all the features required to make websites accessible to folks who use screen readers or rely on keyboard navigation or other assistive technologies. So ARIA is a way to address those deficiencies.
One of the first things to keep in mind is only use ARIA when absolutely necessary. I think this is a thing that we see a lot, where people throw ARIA at problems when maybe it’s not appropriate. Ideally, native HTML should be used to provide the proper semantics and structure required by screen readers, but sometimes, that’s not possible, either because we have limited control over the code that we’re working with or you’re creating something complicated that doesn’t map to native HTML elements, and in those cases, ARIA is a really valuable tool.
Generally speaking, along that same theme, no ARIA is better than bad ARIA. ARIA roles, states, and properties are like CSS for assistant technologies. For screen readers, ARIA influences the accessibility tree by controlling the audible rendering of the non-visual experience, just like CSS influences the visual presentation of a web page. So incorrect ARIA misrepresents that visual experience and can have potentially devastating effects for the non-visual experience.
[Five rules of ARIA use]
So there are five rules of ARIA use. We’ll go through these real quick.
The first rule of ARIA is you do not use ARIA. Again, this is going to be a theme throughout the presentation. Really use it as the last resort. So the first rule is to use native HTML whenever possible. It is the foundation of web accessibility. ARIA should not be used if native HTML can provide the sufficient structure and semantics for your web page, and when used incorrectly, ARIA can introduce significant accessibility barriers, as we mentioned.
Rule number two: don’t change native HTML semantics unless you really have to. Most HTML elements have default semantics that are conveyed to screen reader users, and when necessary, ARIA can override and change those semantics. So we just want to be really careful when we do that, and we’ll see some examples later on where we talk about this.
Rule number three: all interactive elements must be usable with the keyboard. ARIA design patterns define standard keyboard interactions for custom widgets and controls, such as tabs and accordions and any stateful user interface component. This allows everyone to use the widget with a keyboard and ensures that instructions provided by screen readers align with the actual functionality in the page. So we obviously want to make sure that we’re not building things that only work with a mouse or only work on hover, for instance. They must be usable with a keyboard.
Rule number four: interactive elements must be properly semantic and visible. So any element that is keyboard fixable must have proper semantics, either via native HTML or a corresponding ARIA role so that it is correctly identified as a link, a button form control, et cetera. Similarly, any element that can receive focus must be visible on the screen. We don’t want hidden things that can receive focus. That becomes really confusing for someone who maybe is not blind but still uses a keyboard to navigate due to a mobility issue.
Rule number five: text describing an interactive element must be presented to the screen reader when the element is encountered. So this, we often talk about it as the “accessible name”, and if native HTML methods aren’t available to provide an accessible name, ARIA can be used to define that. And again, we’ll see examples of all these rules in a little bit.
[Main features of ARIA: roles, properties, and states]
So there are three main features of ARIA: roles, properties, and states. Roles define what an element is or does, and many of these are so-called landmark roles and they replicate the semantics of native HTML5 sectioning elements, such as role="navigation"
is the same as a nav element. role="contentinfo"
is the same as footer. But there are some others that describe page components, such as search, tablist, tab that do not have a native HTML counterpart. There’s no tablist tag in HTML.
Properties. These components are used to give elements extra semantics. For example, aria-required="true"
specifies that a form input needs to be filled in order to be valid. And aria-labelledby="some-id"
enables authors to reference other elements on the page to define an accessible name, which is not possible with the HTML label tag. So you can write a web page where an H2 with a specific ID is labeling something else on the page.
And the third component of ARIA are states. States define the current condition of an element. So aria-expanded="true"
or “false” convey to a screen reader that a collapsible element, like an accordion, is either active and expanded and invisible or inactive, collapsed, and hidden. These things are then announced to the screen reader. So you click– you activate a an accordion, the screen reader will indicate that the accordion is now expanded and then that person can continue navigating through it.
[Examples]
So now, we’re going to go into the meat of the presentation and go through several examples of when you should use ARIA.
[Defining landmarks]
And the first one we’ve touched on is defining landmarks. ARIA’s role attribute can define landmarks that either replicate the semantics of HTML sectioning elements, such as nav and header, or go beyond HTML to provide semantics to complex widgets like tablist, tab, listbox, et cetera.
So here’s a simple web page example using the native HTML5 tags.
<body>
<header>
<h1>...</h1>
<nav>
<ul>...</ul>
</nav>
</header>
<main>
<article>...</article>
<nav>
<ul>...</ul>
</nav>
</main>
<footer>...</footer>
</body>
We have a header. We’ve got a couple of nav items there. We have a main section, article, and a footer. Typical web page structure.
If you’re working on code where you can’t use native HTML for whatever reason, you’re retrofitting something that’s old, ARIA roles can be added to provide landmark views for assistive technologies. So here, we have the same example as before, but instead of the native HTML5 tags, we’ve just added these ARIA roles to provide those landmark cues for screen readers.
<body>
<div role="banner">
<h1>...</h1>
<div role="navigation">
<ul>...</ul>
</div>
</div>
<div role="main">
<div role="article">...</div>
<div role="navigation">
<ul>...</ul>
</div>
</div>
<div role="contentinfo">...</div>
</body>
So we have role="banner"
, a couple role="navigation"
, main article, and contentinfo.
One thing to be aware of is when an ARIA landmark, a type of ARIA landmark, appears more than once on a page, we need to differentiate those landmarks for screen readers using an ARIA label. This is really common with the main and sub navigation bars or something on a website but can also occur when there are multiple custom widgets like accordions.
So here’s an example. We have two nav elements.
<body>
<header>
<h1>...</h1>
<nav aria-label="primary">
<ul>...</ul>
</nav>
</header>
<main>
<article>...</article>
<nav aria-label="secondary">
<ul>...</ul>
</nav>
</main>
<footer>...</footer>
</body>
The first one is the main navigation bar in the header. So we give it an ARIA label of “primary”, and then we have a second nav element sub navigation, and we give it an ARIA label of “secondary”. You don’t need to include words like “nav” or “navigation” in the ARIA label because the screen reader is already going to announce the nav element as navigation. Similar to Alt text, you don’t need to put “image of such and such” on an image because the screen reader is already going announce that it’s on an image.
[Announcing dynamic content updates]
So a second example of using ARIA is to announce dynamic content updates. With AJAX where content is updating on the page without a page refresh, by default, screen readers have a really hard time with announcing dynamic content changes. They just really can’t do it. So we can use the aria-live attribute on an element to inform screen reader users when an area of content is dynamically updated. So if you have some JavaScript, an API that does a dynamic content update inside of a particular div or section element, you can add aria-live, and there are three options, which we’ll talk about. And that will instruct a screen reader to announce changes to that element.
So here, we have an example. It’s a section, and it’s got aria-live="polite"
, and so when things change inside of there, the screen reader will convey that to the user.
<section aria-live="polite">...</section>
So as I said, there are three options for aria-live. “Off” is the default, nothing is announced. “Polite” is– updates are only announced if the user is idle, and then “assertive” updates are announced as soon as possible. So normally, only polite is used. A region that receives updates that are important for a user to hear but not so rapid is to be annoying should have aria-live="polite"
. So when a user stops doing what they’re doing or the screen reader stops announcing what it’s currently announcing, then the content change will be announced.
aria-live="assertive"
should really only be used for time sensitive critical notifications that absolutely require the user’s attention immediately. It’s going to interrupt any announcement a screen reader is currently making. So it can be really annoying and disruptive to really only be used on examples of things like a session timeout. That would be one where it would be appropriate to use aria-live="assertive"
or if you’ve built a quiz or something and the user has two minutes to answer a question and then the page refreshes or goes on to the next question. aria-live="assertive"
would be appropriate there, but generally speaking, we want to stick with “polite”.
So with aria-live, a screen reader’s default behavior is to read out only the piece of text that updates. Not necessarily any surrounding text within that live region. That may be desirable, but if it’s not, it wouldn’t make any sense if like only one word changes if that was what was announced. There’s an additional attribute. A property called aria-atomic.
So that property could be used in conjunction with aria-live to set whether or not the screen reader should even announce anything within the region as a whole. So a value of true will announce everything along with the region’s label if one is defined.
[Creating accessible labels and descriptions]
So the next example, and this is one that’s probably one of the more common uses and you all may be familiar with this aspect of ARIA already. Creating accessible labels and descriptions for elements. Ideally, elements should be labeled with visible, clearly written text using HTML. We’ve all talked about that so far in this session. This approach is the simplest. It’s easiest to maintain. It’s the most helpful for people with cognitive disabilities. However, ARIA is the only way to add accessible labels or descriptions to an element if native HTML or native accessible text is not available. So you want to use ARIA when HTML labels are not possible.
Native HTML facilitates associations that support accessibility like the label tag for form inputs or a caption tagged for data table descriptions, TH for row and column headers, et cetera. When those can’t be used, we can use ARIA to fill in the blanks with aria-label and aria-labelledby. So these are the two mechanisms for adding labels and descriptions to elements with these two attributes.
So aria-labelledby. It programmatically associates an element with text that functions as a descriptive label, but it isn’t wrapped in an HTML labeling element like a label tag. So it’s aria-labelledby. The ARIA property references the ID or multiple IDs of the elements acting as its label.
Here’s a simple example. This is a section, and we have aria-labelledby="filter-heading"
, which corresponds to the ID on this H2, which reads “Search Filters”.
<section aria-labelledby="filter-heading">
<h2 id="filter-heading">Search Filters</h2>
...
</section>
So when a screen reader encounters this section, it’s going to announce this section as “Search Filters”.
The more common labeling attribute in ARIA, which again, I’m sure all of you are familiar with is the aria-label property, which allows you to apply the label text directly in the attribute value. So we may use this a lot. Here’s a similar example to the previous one.
<section aria-label="Search Filters">
<h2>Filters</h2>
...
</section>
Even though the H2 text is “Filters”, this section will be labeled by the more specific aria-label value of “Search Filters”.
We also– you see this a lot with when you have a link that says “read more”, we could put an aria-label on that link to provide additional, more meaningful accessible text for that link.
So just a couple of things to consider with aria-labels. Using them to define labels, there’s a couple constraints that you need to be aware of. They only work on labelable HTML elements. In order to be assigned an ARIA label, an element must be labelable. So a link, a button, or a form control. Or having specific HTML or ARIA semantics. So many elements are not labelable, such as a p tag or a div tag or a span, unless they’re assigned an appropriate ARIA role. I’ve actually noticed that some screen readers will ignore this and will read out an aria-label on a technically non-labelable element, but that behavior is not consistent across screen readers.
And we have examples of this stuff referenced in the deck, and we’ll share that with you all after the presentation so you’ll have access to links that go into this in more detail.
A couple other things to consider or be aware of with ARIA labels is they override the default HTML elements text and accessible names. So if you have a form input that already has a label on it and then you add an aria-label or an aria-labelledby, the label will not be read. So you really don’t want to override the native HTML accessible text unless you really have to or there’s a compelling reason why it would help a screen reader user better understand the content. And then this is one that’s also a little tricky, or not tricky, but something to keep in mind is WCAG requires that the visible text label for an element be included within its accessible name, which is read by a screen reader. So when using an ARIA label, you just ensure consistency between what sighted users see and what the screen reader user hears, and so here’s the classic vague link text example.
So here, we have a link where the accessible where the text is just “read more” and that’s too vague. It’s a WCAG failure. And so it requires an ARIA label.
<a href="...">Read more</a>
And so here’s two examples of that. The first example, the ARIA label says “About UChicago” but the visible text is “Read more”.
<a href="..." aria-label="About UChicago">Read More</a>
So that’s technically a violation, even though “About UChicago” is good link text, but because the visible text is “Read more”, the correct way to add an ARIA label for this would be to have it read “Read more about UChicago”.
<a href="..." aria-label="Read more about UChicago">Read more</a>
The visible text needs to be included in the accessible text that’s announced.
We have another training session I think we’re going to try and do with y’all at some point about manually assessing your website for accessibility, but really, the best way to ensure that your ARIA labels and descriptions have been implemented correctly is to listen with a screen reader. You can also inspect the accessible name and description using your browser’s developer tools, but just quickly going through the page with a screen reader will help to validate if everything makes sense.
[Enhancing the accessibility of non-semantic controls and custom widgets]
All right, so the final example. This is the most complex one we’ll go through is enhancing the accessibility of non-semantic controls and custom widgets. So when HTML, CSS, and JavaScript are used to create a complex widget or modify some native control, accessibility can really suffer. We see this with– we all know carousels are real tricky to do well with in regards to accessibility. So custom controls might not be keyboard accessible. Screen reader users will find it difficult to determine what the widget does if there are no semantics or other clues added to the widget. So ARIA can extend the accessibility of HTML. In these situations, ARIA can help fill in the blanks with a combination of roles like button, listbox, or tablists. Properties like aria-required, and states such as aria-expanded to provide further information as to the elements purpose.
You can also help enhance the keyboard accessibility of an element. So one of the key strengths of HTML with respect to accessibility is the built in keyboard support of elements such as buttons, form inputs, and links. Generally, you can use the Tab key to move between controls and Enter or Return key to select or activated control, and other keys such as the up and down arrows to move between options in a select box. However, sometimes, you’ll end up having to write code that either uses non-semantic elements for buttons or other controls or uses focus-able controls for not the right purpose. Either you’re fixing some bad code that you’ve inherited or you’re building out a complex widget, and so you get into a situation where the element is not keyboard accessible.
So in terms of making non-focusable code focusable, ARIA extends the tabindex attribute with a couple of values. So tabindex="0"
. This allows elements that are not normally keyboard focusable, such as div, span, p tag, or a tag with no href to receive keyboard focus. This is the most useful value of tabindex. It’s the one that’s most commonly used, and so if you’re working on a complex widget, instead of using a button tag, let’s say it’s a carousel like the forward and back button or something is just a div. You can put tabindex="0"
on those divs and then those elements can receive focus via keyboard.
The second example is tabindex="-1"
, and what this does is it removes– just a couple of things. It removes interactive elements from the default tab order, and in most cases, this is not something you want to do. However, if it’s added to a non-interactive element like a p tag or a div or a span, tabindex="-1"
will allow that element to receive programmatic focus with focus JavaScript scripting. So this can be really useful for elements that should not be navigated to normally using the Tab key but need to have keyboard focus set to them. A classic example is like a modal dialog window that should receive focus when it is opened. So you spawn, you click a button, and it opens up a modal. But maybe that modal in the code order is at the bottom of your document. So what you would need to do is in the JavaScript that controls that modal, you would put a tabindex="-1"
on the modal and then move focus to that modal once it has been activated.
So here’s an example of tabindex="0"
. We’re retrofitting a custom button. There’s some divs, they’re supposed to function like buttons, and they need to have the ability to be focused.
<div role="button" tabindex="0">First Button</div>
<div role="button" tabindex="0">Second Button</div>
<div role="button" tabindex="0">Third Button</div>
So they have a role="button"
, and then a tabindex="0"
. So these now– the user is tabbing through the page with a keyboard. These elements can receive keyboard focus. Ideally, you just use the button tag, but if you can’t for whatever reason, you can use ARIA to replicate the default behavior of a native button tag.
So there are a whole host of other ARIA roles that can define common UI features that go beyond what’s available in standard HTML, such as combobox slider, tabpanel, tree. We’re going to go through in this final example a complex tab widget, which uses some of these ARIA-specific roles.
So in the next slide, there’s a simple tab pattern markup. Uses a UL containing the tabs the user would click, and then the corresponding tab panels that become visible or invisible, depending on which tab is selected. The actual tab functionality is controlled by JavaScript. We’re not going to get into that here. We’re just going to look at the HTML, but in this first example, nothing would be conveyed to a screen reader about the purpose of this widget, nor would the tabs be keyboard accessible. So here we have this basic pattern.
<div class="my-tabs">
<ul>
<li id="tab-one">Tab 1</li>
<li id="tab-two">Tab 2</li>
</ul>
<div class="tabpanel-group">
<div id="panel-one">...</div>
<div id="panel-two">...</div>
</div>
</div>
As far as a screen reader is concerned, this is just a basic unordered list. And then a couple divs. So it might announce the content if you were navigating through, but you wouldn’t be able to interact with this at all, and there would be no indication to the user that they’re on one tab versus another tab, so that could be confusing.
So the first step to improving the accessibility of this pattern is to define the tab list, which is– so the list of tabs, the individual tabs, and then the tab panels with those roles for assistive technology. So here, we’ve added these three roles. The UL for the tabs is a tablist. Each LI is a tab, and then each div there is the tabpanel, and so now, a user encounters this with a screen reader. They’ll at least know they’re on a tab widget. That will be announced.
<div id="my-tabs">
<ul role="tablist">
<li id="tab-one" role="tab">Tab 1</li>
<li id="tab-two" role="tab">Tab 2</li>
</ul>
<div class="tabpanel-group">
<div id="panel-one" role="tabpanel">...</div>
<div id="panel-two" role="tabpanel">...</div>
</div>
</div>
They still won’t be able to interact with it really, and the linkages between tab 1, tab 2, and then it’s their corresponding tab panel still isn’t present here.
Audience: Hey, Jack. Quick question. Tablist and tabpanel. Is there any difference between the two or what would be an example of one versus the other?
Jack: So the tablist is the actual tabs that would run across the top that you would click. And so the tablists– so the tablist is the container of the tabs. So what you click to trigger a tabpanel to open or close.
Audience: That makes sense. Thank you.
Jack: Yep.
So we’re going to move on to adding ARIA properties to these various elements so that the tabs are programmatically related to their corresponding tabpanels. We’re also going to make those tabs keyboard accessible by using the tabindex attribute that we just talked about. So here’s that same example. We’re adding more stuff.
<div id="my-tabs">
<ul role="tablist">
<li id="tab-one" role="tab" aria-controls="panel-one" tabindex="0">Tab 1</li>
<li id="tab-two" role="tab" aria-controls="panel-two" tabindex="0">Tab 2</li>
</ul>
<div class="tabpanel-group">
<div id="panel-one" role="tabpanel">...</div>
<div id="panel-two" role="tabpanel">...</div>
</div>
</div>
So we’ve added an aria-controls attribute to both of the tabs, and the values of those correspond to the IDs on the two tabpanels. So we’re now telling the screen reader that tab 1 controls panel 1, tab 2 controls panel 2, and we’ve added that tabindex attribute to the two tabs, so those now can receive keyboard focus. You could also wrap the tab 1, tab 2 text in a button, and that would also, again, you could use native HTML for some of this. But for this basic example, we’ll just stick to all ARIA.
And then finally, we’re going to add states to this tab widget so that the active and inactive state of the tabs and tab panels are properly conveyed, and we’re going to use aria-selected and aria-hidden attributes. These would be toggled by a JavaScript, so you click one of the tabs, it opens one of the tab panels, and it changes the attributes on those elements. So in the following example, tab 1 has been clicked and is active.
<div id="my-tabs">
<ul role="tablist">
<li id="tab-one" role="tab" aria-controls="panel-one" tabindex="0" aria-selected="true">Tab 1</li>
<li id="tab-two" role="tab" aria-controls="panel-two" tabindex="0" aria-selected="false">Tab 2</li>
</ul>
<div class="tabpanel-group">
<div id="panel-one" role="tabpanel" aria-hidden="false">...</div>
<div id="panel-two" role="tabpanel" aria-hidden="true">...</div>
</div>
</div>
So tab 1 has an aria-selected="true"
, tab 2 is aria-selected="false"
. And then in the tab panel section, the panel 1 is aria-hidden="false"
. And panel 2, aria-hidden="true"
. So tab 1 has been selected and panel 1 is visible to the user. Putting it all together. And so that’s basically it.
[Final Thoughts]
Just a few final thoughts. So as we talked about throughout the presentation, ARIA can extend the accessibility of native HTML. It provides methods to convey information to assistive technology that just isn’t possible with native HTML, such as defining a place for dynamic content is loaded or the expanded collapsed state of a widget. It’s very powerful, and when used properly can greatly enhance the accessibility of web content. Used incorrectly, however, ARIA can have devastating effects on accessibility. So we always want to be aware of that.
It can be used to improve bad HTML or old code. It’s often used as a polyfill for non-semantic HTML or bad information architecture, such as defining landmark roles when native HTML tags exist or correcting for vague link text like “Click Here” or “Read More”.
We continue to stress only use ARIA when it is absolutely necessary. Really try to leverage well-structured and semantic native HTML in your code, and meaningful accessible text in your content as much as possible and only use ARIA when absolutely necessary.
So I mean, y’all know where to find us. But you can always email digitalaccessibility@uchicago.edu. That goes to the whole team. We’re here to provide resources for campus, so like we said, if you have any questions, don’t hesitate to reach out to Thalia or to me. We’d be happy to assist.
Audience: Well, thank you very much.
Jack: Absolutely. Thank you.
[References]
- Slide 1
- WebAIM: Introduction to ARIA – Accessible Rich Internet Applications
- Introduction to ARIA | Web Fundamentals | Google Developers
- ARIA – Accessibility | MDN
- Slide 7
- No ARIA is better than Bad ARIA – WAI-ARIA Authoring Practices 1.2
- Slides 10–11, 13
- WebAIM: Introduction to ARIA – Rules of ARIA Use
- Slide 12
- Design Patterns and Widgets – WAI-ARIA Authoring Practices 1.2
- Slide 14
- WebAIM: Decoding Label and Name for Accessibility
- Slides 16–18
- Three main features of ARIA | MDN
- Slides 26–30
- ARIA live regions | MDN
- Slide 39
- Short note on aria-label, aria-labelledby, and aria-describedby
- Slide 41
- Understanding Success Criterion 2.5.3: Label in Name
- Slide 44
- WebAIM: Testing with Screen Readers – Questions and Answers
- Slide 54
- Deque University Code Library