Using ARIA Roles for Accessibility in WordPress

#
By Mike Davey, Senior Editor

One way to enhance the accessibility of your WordPress projects is with ARIA roles, attributes added to HTML elements to provide semantic meaning and improve accessibility for users of assistive technologies. ARIA roles define the purpose or function of an element, allowing screen readers and other tools to present and support interaction with web content in a way that is consistent with user expectations.

In this article, we’ll look at the ins and outs of implementing ARIA roles in WordPress themes and plugins, and cover practical techniques that you can start using right away to make your sites more inclusive and user-friendly for everyone

Understanding ARIA Roles

ARIA roles are a key component of the Web Accessibility Initiative’s Accessible Rich Internet Applications (WAI-ARIA) specification. These roles provide semantic meaning to content, making it easier for assistive technologies to interpret and present information to users with disabilities.

At its core, an ARIA role is an attribute you can add to an HTML element to clearly define its purpose. This is particularly useful when the default HTML semantics don’t accurately describe the element’s function. For example, you might use a <div> for styling purposes, but want screen readers to treat it as a button.

In WordPress development, ARIA roles become especially valuable when creating complex layouts or interactive elements that go beyond basic HTML structures. They help bridge the gap between visual design and accessible functionality, ensuring that all users can navigate and interact with your WordPress sites effectively.

Here’s a simple example of an ARIA role in action:

<div role="button" tabindex="0" onclick="submitForm()">
    Submit
</div>

In this case, we’ve turned a <div> into a functional button that’s recognizable by assistive technologies.

ARIA roles can be broadly categorized into several types:

  • Landmark roles: These define regions of the page (e.g., banner, navigation, main).
  • Widget roles: These describe interactive elements (e.g., button, tablist, menu).
  • Document structure roles: These describe the structure of content (e.g., article, list, table).

ARIA roles are powerful, but should be used judiciously. The first rule is don’t use ARIA if native HTML elements can provide the semantics and behavior you need. Always prioritize semantic HTML, and use ARIA roles to enhance, not replace, the inherent accessibility of well-structured markup.

Common ARIA Roles in WordPress

When developing WordPress themes and plugins, certain ARIA roles are particularly useful and frequently implemented. Let’s take a look at some of the most common roles you’ll encounter and how they apply to typical WordPress structures.

The banner role is typically used for the site header, which often contains the site title, logo, and primary navigation. In WordPress, this usually corresponds to the <header> element in your theme’s header.php file:

<header role="banner">
    <?php get_template_part( 'template-parts/header/site-header' ); ?>
</header>

The navigation role is used for major navigation blocks. In WordPress, you’ll often use this for the primary menu:

<nav role="navigation" aria-label="Primary Menu">
    <?php
    wp_nav_menu( array(
        'theme_location' => 'primary',
        'menu_class'     => 'primary-menu',
    ) );
    ?>
</nav>

The main role denotes the primary content area of your WordPress site. This is typically used in your theme’s index.php, single.php, or page.php files:

<main id="site-content" role="main">
    <?php
    if ( have_posts() ) {
        while ( have_posts() ) {
            the_post();
            get_template_part( 'template-parts/content/content', get_post_type() );
        }
    }
    ?>
</main>

The complementary role is perfect for sidebar content that supplements the main content but remains meaningful on its own. In WordPress, this often applies to widget areas:

<aside id="secondary" class="widget-area" role="complementary">
    <?php dynamic_sidebar( 'sidebar-1' ); ?>
</aside>

The contentinfo role is typically used for the site footer, which often contains copyright information, secondary links, and other site-wide details:

<footer id="colophon" role="contentinfo">
    <?php get_template_part( 'template-parts/footer/site-info' ); ?>
</footer>

Implementing ARIA Roles in WordPress Themes

When developing WordPress themes, incorporating ARIA roles can help to enhance accessibility.

Adding Roles to Template Files

To add ARIA roles to your WordPress theme, you’ll need to modify your template files. Here are some common places to implement roles:

In header.php:

<header id="masthead" class="site-header" role="banner">
    <!-- Header content -->
</header>

<nav id="site-navigation" class="main-navigation" role="navigation">
    <?php
    wp_nav_menu( array(
        'theme_location' => 'primary',
        'menu_id'        => 'primary-menu',
    ) );
    ?>
</nav>

In index.php or other content files:

<main id="primary" class="site-main" role="main">
    <?php
    if ( have_posts() ) :
        while ( have_posts() ) :
            the_post();
            get_template_part( 'template-parts/content', get_post_type() );
        endwhile;
    endif;
    ?>
</main>

In sidebar.php:

<aside id="secondary" class="widget-area" role="complementary">
    <?php dynamic_sidebar( 'sidebar-1' ); ?>
</aside>

In footer.php:

<footer id="colophon" class="site-footer" role="contentinfo">
    <!-- Footer content -->
</footer>

Best Practices for Using ARIA Roles in Theme Development

As we mentioned earlier, make sure to prioritize semantic HTML elements as the foundation of your structure. ARIA roles should be used to supplement this foundation, providing additional context where necessary, rather than replacing proper HTML semantics. Consistency is key, so apply roles uniformly to similar elements throughout your templates.

Exercise restraint when using ARIA roles. Only add them in situations where they provide additional context that isn’t already conveyed by semantic HTML.

To ensure the effectiveness of your implementation, it’s essential to test your theme with screen readers. This practice helps verify that the roles are being interpreted correctly and truly enhancing the user experience for those relying on assistive technologies.

Consider including landmarks to define regions of the page, such as main, navigation, and footer. Also, ensure that interactive elements like buttons and links have clear, descriptive text or labels. Lastly, use ARIA states and properties to convey dynamic content changes, such as expanded/collapsed states for accordions or menus.

ARIA Roles in WordPress Plugins

Incorporating ARIA roles may be even more important when developing plugins, as plugins often add dynamic content and interactive elements to a site, making accessibility considerations even more important.

Considerations for Plugin Developers

  1. Content Injection: When your plugin injects content into the page, ensure it includes appropriate ARIA roles. This is especially important for dynamically generated content that might not be part of the initial page load.

  2. Interactive Elements: If your plugin adds interactive elements like modals, accordions, or tabbed interfaces, ARIA roles are essential for making these accessible.

  3. State Management: Use ARIA states and properties to convey the current state of dynamic elements to assistive technologies.

Implementing Roles in Dynamic Content

Here’s an example of how you might add ARIA roles to a custom widget created by a plugin:

function my_custom_widget_output() {
    $output = '<div class="my-custom-widget" role="complementary">';
    $output .= '<h2 id="widget-title">Widget Title</h2>';
    $output .= '<ul role="list">';
    // Add list items here
    $output .= '</ul>';
    $output .= '</div>';

    echo $output;
}

For more complex interactive elements, you might use JavaScript to manage ARIA states:

function toggleAccordion(element) {
    var expanded = element.getAttribute('aria-expanded') === 'true' || false;
    element.setAttribute('aria-expanded', !expanded);
    var panel = document.getElementById(element.getAttribute('aria-controls'));
    panel.hidden = expanded;
}

Advanced ARIA Techniques for WordPress

As you become more comfortable with basic ARIA implementations, you can explore advanced techniques that can significantly enhance the accessibility of your WordPress sites, especially for complex interactive elements.

Using ARIA Labels and Descriptions

ARIA labels and descriptions provide additional context to elements, making them easier to understand for users of assistive technologies.

aria-label: Use this when there’s no visible text label for an element.

<button aria-label="Close modal">X</button>

aria-labelledby: Use this to associate an element with a visible text label elsewhere in the DOM.

<h2 id="section-title">Latest Posts</h2>
<div aria-labelledby="section-title">
    <!-- Content here -->
</div>

aria-describedby: Use this to provide additional descriptive information about an element.

function custom_form_field() {
    $output = '<label for="username">Username</label>';
    $output .= '<input type="text" id="username" aria-describedby="username-hint">';
    $output .= '<p id="username-hint">Must be at least 5 characters long</p>';
    return $output;
}

Managing Focus with ARIA

Proper focus management is crucial for keyboard navigation. Here are some techniques:

Setting initial focus: Use JavaScript to set focus on the most relevant element when a new section loads.

document.addEventListener('DOMContentLoaded', function() {
    document.getElementById('main-content').focus();
});

Trapping focus in modals: Ensure that focus stays within modal dialogs when they’re open.

function trapFocus(element) {
    var focusableEls = element.querySelectorAll('a[href]:not([disabled]), button:not([disabled]), textarea:not([disabled]), input[type="text"]:not([disabled]), input[type="radio"]:not([disabled]), input[type="checkbox"]:not([disabled]), select:not([disabled])');
    var firstFocusableEl = focusableEls;
    var lastFocusableEl = focusableEls[focusableEls.length - 1];

    element.addEventListener('keydown', function(e) {
        var isTabPressed = (e.key === 'Tab' || e.keyCode === 9);

        if (!isTabPressed) {
            return;
        }

        if (e.shiftKey) {
            if (document.activeElement === firstFocusableEl) {
                lastFocusableEl.focus();
                e.preventDefault();
            }
        } else {
            if (document.activeElement === lastFocusableEl) {
                firstFocusableEl.focus();
                e.preventDefault();
            }
        }
    });
}

Managing focus for dynamic content: When content changes dynamically, use aria-live regions to announce changes and manage focus appropriately.

function dynamic_content_area() {
    return '<div id="live-region" aria-live="polite"></div>';
}

add_shortcode('live_region', 'dynamic_content_area');

Implementing Complex Widgets

Complex widgets like tabs and accordions require careful ARIA implementation for accessibility.

Tabs

The code example below creates a tabbed interface with two tabs and their corresponding content panels. The outer <div> with role="tablist" acts as a container for the tab buttons. Each tab button is given a role="tab" and associated with its content panel using aria-controls. The aria-selected attribute indicates which tab is currently active. The content panels are marked with role="tabpanel" and linked back to their respective tabs using aria-labelledby. This structure allows screen readers to understand the relationship between tabs and their content.

function accessible_tabs() {
    $output = '<div class="tabs" role="tablist">';
    $output .= '<button id="tab1" class="tab" role="tab" aria-selected="true" aria-controls="panel1">Tab 1</button>';
    $output .= '<button id="tab2" class="tab" role="tab" aria-selected="false" aria-controls="panel2">Tab 2</button>';
    $output .= '</div>';
    $output .= '<div id="panel1" role="tabpanel" aria-labelledby="tab1">Content 1</div>';
    $output .= '<div id="panel2" role="tabpanel" aria-labelledby="tab2" hidden>Content 2</div>';
    return $output;
}

add_shortcode('accessible_tabs', 'accessible_tabs');

Accordions:

The example below showcases a single expandable section. The accordion header is wrapped in an <h3> tag, containing a button that toggles the accordion. This button uses aria-expanded to indicate its current state and aria-controls to associate it with the content panel. The content panel itself is given a role="region" and linked back to its header using aria-labelledby. The hidden attribute is used to initially hide the content. This structure enables screen readers to understand the accordion’s functionality and current state, improving the accessibility of the expandable content.

function accessible_accordion() {
    $output = '<div class="accordion">';
    $output .= '<h3>';
    $output .= '<button aria-expanded="false" class="accordion-trigger" aria-controls="sect1" id="accordion1id">';
    $output .= '<span class="accordion-title">Section 1</span>';
    $output .= '<span class="accordion-icon"></span>';
    $output .= '</button>';
    $output .= '</h3>';
    $output .= '<div id="sect1" role="region" aria-labelledby="accordion1id" class="accordion-panel" hidden="">';
    $output .= '<div>';
    $output .= '<!-- Panel content -->';
    $output .= '</div>';
    $output .= '</div>';
    $output .= '</div>';
    return $output;
}

add_shortcode('accessible_accordion', 'accessible_accordion');

Testing ARIA Roles in WordPress

Implementing ARIA roles is only half the battle.Thorough testing is crucial.

Tools for Accessibility Testing

There are plugins that can run automated accessibility tests, some of which we’ve discussed previously.

Aside from plugins, screen readers are essential for testing how ARIA roles are interpreted by assistive technologies. VoiceOver for macOS, NVDA for Windows, and JAWS are popular choices. By using these screen readers, you can experience your site as users do and identify any issues with your ARIA implementation.

Finally, don’t overlook the power of browser developer tools. Modern browsers include built-in accessibility auditing features that can help identify ARIA-related issues.

Common Pitfalls and How to Avoid Them

At the risk of repeating ourselves, one of the most common mistakes in ARIA implementation is simply overuse. It’s tempting to add ARIA roles to every element, but this can actually harm accessibility. Use native HTML elements whenever possible and only add ARIA roles when absolutely necessary.

Incorrect formatting of ARIA attributes is another frequent issue. Ensure that your ARIA attributes follow the correct syntax and avoid embedding markup or special characters in attribute values. For example, the aria-label attribute should contain plain text, not HTML.

Misusing aria-hidden can have serious consequences for accessibility. Be cautious when hiding content from screen readers and carefully assess whether elements should truly be hidden from assistive technologies.

Dynamic content presents its own challenges. Don’t forget to update ARIA states (like aria-expanded) when the UI changes. Use JavaScript to dynamically update these states and properties as users interact with your site.

Remember that ARIA roles don’t add functionality to elements on their own. Ensure that elements with ARIA roles also have the necessary JavaScript to handle interactions and keyboard events.

Wrapping Up

Regardless of how you approach accessibility, it’s important to keep the end goal in mind: creating an inclusive user experience. Implementing ARIA roles isn’t the goal, it’s just a tool that can help you reach it.

Accessibility shouldn’t be an add-on or an afterthought—it’s an essential aspect of web development that benefits all users.

Rather than a goal, it might be best to think of accessibility as a journey, not a destination. Web standards and best practices evolve, and so should our approach to accessibility. Stay informed about the latest WCAG guidelines, WordPress accessibility standards, and emerging technologies that can help make your sites more inclusive.

About the Author

Mike Davey Senior Editor

Mike is an editor and writer based in Hamilton, Ontario, with an extensive background in business-to-business communications and marketing. His hobbies include reading, writing, and wrangling his four children.