You’ve probably heard, “The first rule of ARIA is don’t use ARIA". This is a tongue-in-cheek reference to the movie Fight Club, but the reality is more nuanced. The real rule is: “Don’t use ARIA, unless you need to.” The TLDR: lean on native HTML whenever possible, but when HTML alone isn’t enough, ARIA fills the gaps. So when do we reach for ARIA in Drupal theming?
In this article, we’ll walk through some of the most common ARIA attributes you’ll encounter when building Drupal sites.
What is ARIA?
ARIA (Accessible Rich Internet Applications) is a set of HTML attributes that give assistive technologies (like screen readers) more context about elements.
For example, ARIA can:
- Tell users whether a button is expanded or collapsed.
- Provide a text label for an icon-only link.
- Mark an image as decorative when it has no real content value.
In short: ARIA fills accessibility gaps, but only when semantics or native HTML don’t do the job.
Commonly Used ARIA Attributes
aria-expanded
If you’ve built a dropdown navigation, you’ve almost certainly used aria-expanded. This attribute communicates the disclosure pattern: a control (like a button) reveals or hides additional content. When toggled, screen readers announce whether the element is expanded or collapsed.
Typical use cases include showing submenus in your site's primary navigation, and showing or hiding anything behind a button.
In this example, we're have a primary navigation menu, with its second item set to a <button>
element that is implementing aria-expanded
. Note that Drupal core's menu system allows you to add <button>
HTML menus directly through the UI.
<nav>
<ul class="menu__list">
<li class="menu__item">
<a class="menu__link" href="/">Home</a>
</li>
<li>
<!-- The `aria-expanded="false" below, indicates that clicking the button will show more content. -->
<button class="menu__link" aria-expanded="false">Services</button>
<ul class="menu__list--level-2">
<li><a href="/services/consulting">Front-end Development</a></li>
<li><a href="/services/training">Dragon Training</a></li>
<li><a href="/services/captaining">Steamboat Captaining</a></li>
</ul>
</li>
</ul>
</nav>
The second level menu is hidden via CSS, and shown when the aria attribute is flipped.
.menu__list--level-2 {
visibility: hidden;
.menu__link[aria-expanded="true"] + & {
visibility: visible;
}
}
Note that when implementing dropdown navigation, be sure to test thoroughly. It’s common that when implementing both hover and click events, the events can fire simultaneously and cancel each other out. Be sure your JavaScript takes this into account. You’ll also want to make sure that hidden submenu links aren’t focusable until visible. Use prevent this by using display: none
or visibility: hidden
(the latter works better with transitions)
aria-label
and aria-labelledby
These attributes are invaluable for labeling controls or landmarks.
Use cases:
- Icon-only links: A magnifying glass link should announce “Search.”
- Ambiguous links: A “More” link should be clarified as “More articles.”
- Landmark navigation: If you have multiple <nav> elements (e.g., primary navigation, footer links, social media), use ARIA to give each one a distinct accessible name.
In the example below, the navigation landmark element is labelled by its heading. Note that the heading has a visually-hidden
CSS class, which hides the element visually, while maintaining it for screen readers. This is useful as it's very common for screen reader users to navigate by jumping from heading to heading.
<nav aria-labelledby="primary-nav-heading">
<h2 id="primary-nav-heading" class="visually-hidden">Primary navigation</h2>
<ul class="menu__list">
...
</ul>
</nav>
ARIA Roles
Roles define what an element is for assistive tech. Use them sparingly, though, native HTML is always better. For instance, don’t use role="button"
on an <a>
tag. Just use <button>
.
That said, roles do have valid uses:
role="group"
Useful for complex composite components like carousels. Within a carousel, it's common to apply role="group"
to the parent container, slide wrappers, and any pagers (you can nest this role). For more information on accessibile carousels, see the ARIA authoring practices guide on carousels.
role="dialog"
You'll see role="dialog
paired with aria-modal="true"
on Drupal core's modal popups. These (obviously) indicate to assistive technology that a dialog that acts like a modal is being displayed. Note that the new <dialog>
HTML element is now widely available across all browsers, so you should be implementing this on new themes, as opposed to adding attributes (see the first rule!).
Note on usage roles in core
In Drupal core, it's common to see both semantic HTML and roles grouped together (e.g. <article role="article"
). This was to ensure compatibility with older versions of Safari, but is no longer needed. In fact, if you want to some quick and easy core credits, you can work on stripping them out.
Wrapping up
Accessibility can be tricky. There's a ton of attributes, and techniques that need to be applied to do it correctly, and overdoing it is generally counter-productive. That being said, proper accessibility is a process. The attributes above, paired with semantic HTML will get you far and make your sites much more usable for those with assistive technology.