CategoryProduct design

Semantic HTML first: accessibility that needs no ARIA

10 min read

Most accessibility problems come from the wrong element, not from a missing ARIA attribute. A button is focusable, keyboard operable, and named by its own text. A div with a click handler is none of that until you rebuild each behavior by hand. Semantic HTML is the first layer because the browser and the screen reader already agree on what those elements mean.

Why semantic HTML is the first layer

The browser reads your markup and builds an accessibility tree. Every element contributes a role, a name, and a state to that tree. Assistive technology reads the tree, not the pixels, so the tree is the only version of your page a screen reader user gets.

WCAG 2.2 is a W3C Recommendation published on 12 December 2024. It writes the requirement as testable success criteria. Success Criterion 1.3.1, at Level A, asks that structure and relationships conveyed through presentation be programmatically determined. Success Criterion 4.1.2, also Level A, asks that the name and role of each user interface component be programmatically determined.

That second criterion carries a note worth reading twice. It says standard HTML controls already meet the criterion when used according to specification. The cheapest path to conformance is therefore to pick the element whose role is already the role you want.

In practice that means nav for navigation, main for the primary content and h1 through h6 for headings. It also means ul and ol for lists, label bound to its input, and fieldset with legend for grouped controls. None of this costs a line of JavaScript.

What the right element solves and what no attribute solves

The right element arrives with behavior attached, and the browser maintains that behavior for you.

  • button brings focus, activation with Enter and Space, a disabled state, and an accessible name taken from its text. MDN describes it as an element activated by mouse, keyboard, finger, voice command, or another assistive technology.
  • a with an href brings the link role, focus, and navigation handled by the browser.
  • details with summary brings expand and collapse with no script and no ARIA.
  • dialog brings modal behavior, focus containment, and the Escape key.

Some problems no attribute can fix. It helps to know which ones, so you stop hunting for one.

  • No attribute gives content its meaning. ARIA can name a control. It can’t decide that a paragraph is a heading, or that three items are a list.
  • No attribute repairs reading order. Success Criterion 1.3.2 asks that a correct reading sequence be programmatically determined. That sequence comes from the document order of your markup.
  • No attribute repairs focus order after a visual reorder. CSS order moves boxes on screen and leaves the tab sequence where it was. MDN warns against CSS that changes the order of focusable elements.
  • No attribute fixes contrast, target size, or text spacing. Those are visual properties, and the criteria that cover them are about CSS.

Focus, keyboard and reading order

Focus is the cursor of the keyboard. What can receive it, and in which order, decides whether a keyboard user can finish the task at all.

Some elements are focusable by default. MDN lists them: a with an href, area with an href, button, input, select, textarea, summary, iframe, object, and frame. They enter the tab sequence in document order. That single fact explains the most common advice in the reference: write the document with the elements in a logical sequence.

tabindex changes that default, and it is easy to misuse. tabindex="0" adds an element to the tab sequence at its position in the source. tabindex="-1" makes an element focusable from script while keeping it out of the tab sequence. A positive value puts the element ahead of the document order, which is why MDN recommends using only 0 and -1.

Success Criterion 2.4.3, at Level A, asks focusable components to receive focus in an order that preserves meaning and operability. Success Criterion 2.4.7, at Level AA, asks for a visible focus indicator. WCAG 2.2 added Success Criterion 2.4.11, Focus Not Obscured at the Minimum level, which covers the sticky header that hides the field you just tabbed into. Interaction state and visible focus are the subject of state and interaction.

Reading order is a separate axis from focus order, and screen reader users move along it by structure. They jump from heading to heading, list to list, landmark to landmark. MDN notes that heading navigation is a common technique and that skipping a level leaves the person wondering where the missing heading went. One h1 per page, then h2, then h3, with no gaps. The old idea that a section could reset the outline was never implemented and is now non-conforming.

When ARIA is necessary and when it makes things worse

ARIA isn’t the enemy. It is the tool for the cases HTML doesn’t cover, and those cases are real.

The First Rule of ARIA Use states the principle and then lists the exceptions. Prefer a native element or attribute that already carries the semantics and behavior you need. Use ARIA in four cases. The feature isn’t implemented in HTML, assistive support for the native element is missing, visual design rules the native element out, or HTML has no such feature at all.

Concrete cases where ARIA is the right answer:

  • Live regions. A filter changes and the page must announce that three results remain. role="status" or aria-live does that, and HTML has no element that announces on its own. Success Criterion 4.1.3, Status Messages at Level AA, exists for exactly this, and it asks for a message that reaches assistive technology without receiving focus.
  • aria-expanded on a custom disclosure control, so the state can be read as well as seen.
  • aria-current="page" on the active navigation link, which is a state HTML doesn’t express.
  • aria-labelledby pointing a region at a heading that already exists, instead of copying the text into a second label.

Where ARIA makes things worse:

  • role="button" on a div with a click handler. The role announces a button and adds nothing else. It doesn’t add focus and it doesn’t add keyboard activation. The Third Rule of ARIA Use requires every interactive ARIA control to be usable with the keyboard, and it names the specific duty: the element must receive focus and respond to both Enter and Space. That duty is now yours to implement.
  • aria-hidden="true" on a focusable element. The Fourth Rule of ARIA Use forbids it, because the result is a user focusing on nothing. The same rule extends to ancestors, since hiding a container hides the interactive children inside it.
  • A role that doesn’t match the behavior. It fails quietly and tells the screen reader something false, which is worse than saying nothing.

One caveat for anyone who wants to cite the rules. The W3C now lists the Using ARIA document as a Discontinued Draft, dated 24 February 2026, and keeps the four rules for reference. The current source for widget patterns is the ARIA Authoring Practices Guide. WAI-ARIA 1.2 itself remains a W3C Recommendation from 6 June 2023.

The common mistake of using ARIA to patch wrong markup

The pattern is familiar. A card should be clickable, so the developer puts role="button" and tabindex="0" on a div. Then an aria-label for the name. Then a keydown handler for Enter, and a second one for Space, because the first one didn’t fire. Forty lines replace one <button>.

The Second Rule of ARIA Use names this directly. Don’t change native semantics unless you really have to, and the specification’s own example is a heading turned into a tab. The repair is the element you should have used, not a better attribute.

The warning sign is pile-up. When a div needs a role, a tabindex, a keydown handler and a label to act like a control, the element is the bug. Change the element and delete the attributes.

There is another sign, pointing the other way. When ARIA repeats what the element already says, it is noise. role="navigation" on a nav adds nothing. role="list" on a ul adds nothing. Redundant ARIA costs maintenance and can drift out of sync with the element.

How to verify, without paid tools

Most of the work is testable with a keyboard, a browser, and patience.

  • Unplug the mouse and tab through the page from the address bar. If focus vanishes or skips a control, you have found a defect rather than a preference. Success Criteria 2.4.7 and 2.4.11 are both about this.
  • Compare the tab order against the visual order. When they disagree, the DOM order is what the keyboard follows, and CSS order is the first suspect.
  • Open the accessibility tree in your browser’s developer tools and read the computed role and name of each control. That is the same information the screen reader receives.
  • Turn off CSS and read the page. The headings, lists and labels that survive are the ones you marked up properly.
  • Zoom to 200 percent and check that nothing is cut off, since reflow is a criterion and not a matter of taste.
  • Check the heading outline for gaps, because a heading list is how many screen reader users skim a page.

But this has a limit. Automated checkers catch a share of defects and none of the meaning. A tool can tell you that an image has alt text. It can’t tell you that the alt text is wrong. A real screen reader session and a real user are the only test for that, and no free script replaces them. The checks that hold up before anyone opens the page are gathered in accessibility you can verify.

The order of work is fixed. Choose the element that already means what you mean. Keep the DOM order true to the visual order. Keep focus visible. Reach for ARIA only where HTML has no answer, and then write as little of it as possible. The ARIA you keep is the ARIA you can still get right a year from now.

A parallel argument about inheriting work instead of repeating it sits in the Material Design post.

Where Nielsen Norman Group disagrees

Nielsen Norman Group doesn’t measure accessibility by conformance. The article on accessibility not being enough states that treating accessibility as a score doesn’t help people with disabilities. A checklist also doesn’t teach anyone to write alt text. The article on inclusive design sets the bar beyond compliance. This post keeps a WCAG success criterion as the testable bar, which is the narrower claim.

One preference runs against the rest of the post. The article on direct against sequential access prefers direct access, while the guidance here is about the sequential path of the Tab key and of the jump from heading to heading.

The other two articles don’t contradict each other. How users read on the web is about scanning a page, and the article on keyboard navigation is about operating it. Different channels, different claims.

Sources

More articles

See all articles