Skip to content

The First Rule of ARIA

Last updated on November 14, 2025

The internet today far exceeds what we initially thought it could be. We’ve advanced so far that we can replicate desktop applications running in the browser. Cloud-based software is everywhere. We’ve crafted frameworks to speed up development and solve the hard parts of server-client communication.

But the same problem keeps happening. We keep rebuilding interactive components using custom coding. And we forget all the things we need to do to make them accessible.

Today I’m looking at a why we should be using more native HTML controls and fewer custom ones. I’ll show you what is included if you use a native control.

The First Rule of ARIA is …

Links and Buttons

We’ll start simple with links and buttons.

A well crafted link will use the <a> element. As it stands, with nothing more added it is a generic inline element. This makes it equivalent with a <span>. We need to add one thing to make it a link, the HREF. Providing a HREF value, even if it is a slice of JavaScript, the pound or hash sigh (#), or a URL. With our element and the HREF, we get the following:

  • Tabindex is set to 0 placing it the tab order
  • Role of link
  • Accessible name will be the text of the link
  • Visited status

A button is even simpler. If we use the <button> element or <input> with a type of submit or button, everything is set. We get the following:

  • Tabindex set to 0
  • Role of button
  • Accessible name will be either the text node or the value set.
<button type="button">My Name</button>
<button type="submit">My Submit button</button>
<input type="button" value="My Input Button" />
<input type="submit" value="My Submit Button" />

Now we can improve our buttons with ARIA depending on how they are used. If it is a menu, navigation, combobox, or accordion we’re likely to add aria-expanded to communicate the state. Or if we have a single choice set of buttons, we could add aria-current to explain which one is current chosen. But this is taking the button beyond it’s most basic function.

Think about the spirit of the guideline

Inputs and Labels

You’ve heard the chorus, “Form fields must have labels!” Let’s examine how we make sure we have accessible names without using ARIA.

First let’s establish that all inputs, textareas, and selects need a visible accessible name. According to WCAG 2.5.3 Label In Name, the visible portion of the label must be included, preferably at the start, of the accessible name. There is room for interpretation in WCAG, in that if there is no visible label, then 2.5.3 doesn’t apply. But if we think about the spirit of the guideline it is to make sure it is easy for speech users to easily access controls. Therefore, if we don’t have visible labels we are explicitly excluding a group of users. The same applies to users with cognitive issues to deal with.

We have two basic ways to label inputs, implicitly and explicitly.

Implicit

With implicit, we wrap the input, select or textarea in the label element.

<label>My First Name: 
  <input name="fname" type="text" value="Nat" />
</label>

Explicit

With the explicit method, we add the for attribute to the label and set the value to the ID of the input.

<label for="fname">My First Name:</label>
<input name="fname" type="text" value="Nat" />

In both cases the label acts as a visible label and accessible name for the input. That gives us compliance under 2.5.3 as well. Further, this method extends the clickable area that a user can activate the field focus with. While less important on a name field than on radio buttons and checkboxes, when the label is added explicitly or implicitly it becomes part of the activation zone of the input. For users with a tremor in their hands, this is extremely helpful.

Landmarks

HTML5 brought us a series of new elements that help define the structure of the page. In the past we had headings. But now we have actual page structure. We’re able to identify the header, navigation, main content, footer, and related sidebars by using the related elements:

  • <header>
  • <nav>
  • <footer>
  • <article>
  • <aside>
  • <section>
  • <main>

These are amazing because we can inform the user of what the content sections are. Each of these elements should have an accessible name describing the content. If you use any one more than once, you must name them. Screen reader users have the ability to navigate by landmarks. If they bring up a site’s landmarks and hear there is a header, nav, main, and footer, they probably don’t need names.

But most sites these days have a header with multiple navs, a main, footer with a nav, and usually 1 sidebar. Inside the main we may have multiple sections and articles. The sidebar may have multiple sections as well.

Tables

Tables. What to say about tables? In the beginning days, they were the only way to truly get your site to layout the way your wanted it to. As they have their own semantics, this became a problem for screen readers. It was tackled in two ways. WCAG provided guidance to only use tables for tabular date and layout. The other way was using ARIA. Placing role=”presentation” on the root <table> element to force the table to “hide” from assistive technology. They also began working on the “grid” role set. While this role was originally meant for tables to provide additional functionality in an accessible way, it can be used with non-table elements to do the same.

Tables get an exception for two way scrolling

But why? Most people will respond that it is a “mobile first” or “responsive” method. Here’s a little secret, tables get an exception for two way scrolling. Stop worrying about how you will make it fit on the small screen and just make a table. Here’s what you get when you build it right:

  • Screen readers already have a built in way to navigate them
  • As you move rows in a given column the row name and value is announced.
  • As you move columns in a given row, the column name and value is announced.

All of this needs to be added with ARIA if you don’t use the table.

<table>
  <caption>My Great Table</caption>
  <thead>
    <tr>
      <th scope="col">Title</th>
      <th scope="col">Author</th>
      <th scope="col">Read?</th>
    </tr>
   </thead>
   <tbody>
    <tr>
      <th scope="row">Hitchhiker's Guide to the Galaxy</th>
      <td>Douglas Adams</td>
      <td>Yes</td>
    </tr>
    <tr>
      <th scope="row">The Stand</th>
      <td>Stephen King</td>
      <td>Yes</td>
    </tr>
    <tr>
      <th scope="row">War and Peace</th>
      <td>Leo Tolstoy</td>
      <td>No</td>
    </tr>
</table>

Other Cool Things

Trying not to make this article too long, I’m offering up a few samples that start building other control types. And it’s when we start building these complex components where ARIA usually comes in. However, we have a few new things in HTML that allow you to cut down on ARIA.

Customizable Selects

Chrome now supports customized styling on selects. This means that you can design the traditional <select> element to look however you want! Of course this isn’t supported across all browsers, but anything built off of Chromium 119 or higher will support it. This means Chrome on all platforms including Android, but not iOS. Opera on all platforms. Edge on all platforms.

Datalist

Did you know that HTML has a built in type-ahead completion component? It certainly does. If you supply an input the list attribute with an ID of a datalist, as the user types they will be presented by the list of options including what they typed.

<label for="superheroes">Favorite Hero:</label>
<input list="supelist" id="superheroes" name="superheroes">
<datalist id="supelist">
  <option value="Superman">Superman</option>
  <option value="Batman">Superman</option>
  <option value="Superman">Batman</option>
  <option value="Spider-man">Spider-man</option>
  <option value="The Tick">The Tick</option>
  <option value="Hawkgirl">Hawkgirl</option>
  <option value="Mr. Terrific">Mr. Terrific</option>
  <option value="Cat Woman">Cat Woman</option>
  <option value="Rogue">Rogue</option>
  <option value="Kitty Pride">Kitty Pride</option>
  <option value="A-Bomb">A-Bomb</option>
</datalist>

Codepen to see it in action.

No JavaScript Accordions

Yes, that’s right. Native HTML accordions. Let’s get some terminology right though. What we are discussing is a disclosure component. When you have a series of disclosures, you have an accordion, akin to the “accordion file” folder.

The <details> element allows you to provide a summary and details. The default state is is closed. It is in the tab order, with the heading acting as the accessible name. It expresses that it is closed or opened.

<details>
   <summary>My very detailed Details</summary>
   <p>I can use other elements to structure this. Such as:</p>
   <ul>
     <li>Paragraphs</li>
     <li>Lists</li>
     <li>Headings</li>
   </ul>
</details>

Articles

Articles are meant to stand on their own. Initially meant for RSS and other syndication, they are used differently now for most cases. However, there are requirements that are often ignored:

  • Must have a header including author, publish date, and title
  • Must have any updated published dates
  • Tags, co-authors, author bio, source site

You can use a footer in the article as well to contain most of this, but the header should have title, date, and author.

Summary

HTML gives you a lot for free. Shift your thinking to use HTML first instead of using a generic container. Using basic HTML, then selectively add ARIA when you need to enhance functionality.

Have some thoughts or feedback come talk to me on Linkedin or BlueSky!

Published ina11ya11y 101accessibilityADAARIAdevelopmentEAAEN 301 549W3CWCAGWeb Content Accessibility Guidelines