WAI-ARIA states and properties: Practical examples

I’ve been trying to include some WAI-ARIA into the project I’m currently working on. Luckily for me I’m using jQuery’s UI dialog and autocomplete plugins and they come with ARIA states and properties straight out of the box! Adding ARIA to my own UI widgets led me to conclude that it’s quite tricky to get right.

I found it difficult to make sense of the specification and getting started took longer than I thought it might. The following are some of the states and properties I looked at:

aria-expanded: state

For pages that have large amounts of data/form editing I have implemented an interface where the user can expand or hide various sections as they wish. Using javascript, I add and update the aria-expanded state dynamically when each section is expanded and hidden.

<section aria-expanded="true" class="expand">
    <p>This section is currently expanded.</p>

<section aria-expanded="false" class="hide">
    <p>This section is currently hidden.</p>

aria-hidden: state

When javascript is enabled, the edit form allows for AJAX submits to save any information that is entered. In this case I have visually removed the submit button from the page and the aria-hidden state can be used to indicate that the element is not visible to any user. Using CSS display:none will hide the content from assistive-technologies (AT) that access the DOM through a rendering engine, so using ARIA in this instance will ensure that ATs accessing the DOM directly will not ‘see’ the element.

$(function() {
    $('button').attr('aria-hidden', 'true');

aria-haspopup: property

Some functionality on the page is not available to those users who are not logged in. When javascript is enabled, instead of redirecting the user to the login page I use a UI dialog box to explain why they can not access those functions. ATs have always had trouble knowing when overlays are active and aria-haspopup property can be used to indicate that the element will trigger items over the top of the main content.

    <li aria-haspopup="true">
        <a href="/login">Function for logged in user</a>
    <li><a href="/nice-features">Function for everyone</a></li>

aria-owns: property

If your popup is not next to the element that triggered it in the DOM, you should use the aria-owns property to infer a parent/child relationship between them. This property’s value should be a unique ID to the popup.

    <li aria-haspopup="true" aria-owns="login-popup">
        <a href="/login">Function for logged in user</a>

... more code ...

<div id="login-popup">
    <p>You must <a href="/login">login</a> to access 
    this feature.</p>

Duplication between HTML and ARIA

Some ARIA attributes seem to duplicate existing HTML attributes. I wanted to add aria-valuemax on a password input that already had the maxlength attribute set. In this case I decided that I should use both variations. The maxlength attribute has been in existence since HTML2.0 so browsers know the user should be prevented from inputting more characters than has been defined. We add aria-valuemax for AT that is specifically looking out for ARIA information.

I misread the spec on the aria-valuemax attribute. Gez Lemon kindly put me straight that aria-valuemin and aria-valuemax were only appropriate for range widgets.

Another example is the new HTML5 required attribute (for form fields that the user is required to complete) which is marked in ARIA by adding the aria-required attribute. The reason for adding both in this situation is that ARIA is quickly gaining support while browsers are only just beginning to support HTML5 and this will ensure your site is as accessible as possible.

More information

Please let me know if I’ve done something silly, it’s simply my interpretation of the spc and I may have got it wrong.