Should you reach for ARIA, or is native HTML usually the better answer?
On this page
Reach for native HTML first, and use ARIA only to fill genuine gaps that native elements cannot cover. Native elements arrive with built-in accessibility semantics, keyboard behavior, and focus handling that you would otherwise have to rebuild by hand, so the rule, often called the first rule of ARIA, is to use the native control whenever one exists and add ARIA sparingly. This is not a stylistic preference; misused ARIA can make an interface less accessible than no ARIA at all, which is why the field’s standing advice is that no ARIA is better than bad ARIA.
The reasoning is that ARIA only changes what assistive technology announces; it does not add any behavior. A <button> is focusable, fires on both Enter and Space, sits in the tab order, and announces as a button, all for free. A <div role="button"> announces as a button and tells a screen reader nothing more, but it is not focusable, does not respond to keyboard activation, and does not trigger on Space or Enter unless you write every bit of that yourself, correctly, including the tabindex and the key handlers. ARIA is a promise about semantics that you, the developer, are then responsible for keeping in behavior. Native elements keep that promise automatically.
The standing of “no ARIA is better than bad ARIA” is backed by hard data: accessibility surveys consistently find that pages using ARIA average more detectable errors than pages without it, because the most common ARIA is applied incorrectly, overriding correct native semantics, pointing at IDs that do not exist, or claiming states the code never updates. A wrong role actively lies to assistive technology, sending users down a path that does not match reality, which is worse than the honest silence of an unstyled but semantically plain element.
A concrete example: a team builds a custom dropdown out of <div>s and reaches for ARIA to make it accessible, adding role="listbox", role="option", aria-selected, and aria-expanded. Done perfectly with full keyboard support it can work, but it is a large, fragile surface to get exactly right, and done partially it announces a listbox that arrow keys do not actually drive. The native <select> element gives all of that, the role, the options, the selected state, keyboard navigation, and the platform’s own picker on mobile, with a single tag and zero ARIA. Native is not the fallback here; it is the better-engineered answer.
There is one real limit: ARIA is genuinely necessary where HTML has no native equivalent. There is no native tab interface, no native tooltip with reliable semantics, no native “this region updated” announcement, so role="tablist", aria-describedby, and aria-live regions are exactly the right tools for those gaps. Even then the discipline holds: prefer any native element that does part of the job (use a real <button> inside your tab strip rather than a div with role="tab" bolted onto a clickable box), and add ARIA only for the semantics native HTML cannot express. ARIA fills holes; it should not replace floors that already exist.
When you build a component, start by asking whether a native element already does this, and use it if one does: <button>, <a>, <select>, <input type="checkbox">, <dialog>, <details>. Reach for ARIA only where you have confirmed no native option fits, and when you do, commit to implementing every behavior the role implies and testing it with an actual screen reader. If you are adding a role to an element that has a native equivalent one tag away, you are working against the grain, and the accessible path is almost always the native one.