skip to content

An audit of a product built largely from `<div>` elements annotated with ARIA roles reports almost no automated violations, yet screen-reader users describe the interface as unusable. Why can incorrect ARIA be worse than no ARIA, and how would you prioritise the fixes?

level: seniorimportance: should knowfreq 45%

answer

  1. assistive tech cannot detect a lie
  2. overrides what the browser already knew
  3. syntax passes, behaviour fails
  4. triage by blocked task
  5. the fix is usually deletion

basics

~20 s

Incorrect ARIA overrides what the browser already knew and makes assistive technology report a widget that does not behave as promised. Automated tools verify attribute syntax, not truthfulness. Fix by deleting wrong ARIA and restoring native elements first.

solid answer

~50 s

ARIA is authoritative: whatever role, state and name you declare is what assistive technology reports, and it will not second-guess you. So a wrong role is not a missing feature, it is misinformation — a user hears "tab, 3 of 5", presses the arrow keys the pattern promises, and nothing moves. With no ARIA at all they would at least hear plain content and could explore it. Automated checkers only see syntax: valid role names, required attributes present, ID references resolving. They cannot know whether the thing you called a tablist behaves like one, which is why a div-and-ARIA codebase can score clean and still fail people. I triage by user impact: first anything that blocks a task — controls unreachable by keyboard or announced as the wrong kind of thing; then wrong or stale states; then names and descriptions. The cheapest fix is usually deletion — replace the div plus ARIA with the native element and remove the attributes entirely.

go deeper

for a junior

Understand that assistive technology repeats whatever ARIA says, so a wrong role misinforms the user. Automated checkers only verify that attributes are well-formed.

for a middle

Explain the override mechanism — an explicit role replaces the element's own semantics in the accessibility tree — and give an example of a promise that is not kept, such as a role implying keyboard behaviour that was never implemented.

for a senior

Show a triage order grounded in blocked tasks, argue for deletion over completion where a native element exists, and describe the behavioural verification (keyboard pass, screen-reader pass, accessibility-tree assertions) that catches what the linter cannot.

for a principal

Own the measurement problem: a rule-count metric produced this codebase. Define what "accessible" means for the organisation, where the gate sits in the pipeline, and who owns the small number of custom widgets that remain justified.

## Why ARIA is dangerous when wrong ARIA declarations are not hints. When you set a role, the browser stops exposing the element's own semantics and exposes yours instead; assistive technology has no way to detect that the declaration is false. That asymmetry is the whole answer: - **Silence is explorable.** An un-annotated div announces its text. A screen-reader user reads it, notices it looks like a control, tries clicking it with a pointer gesture or a virtual-cursor activation, and often gets somewhere. - **A false promise is a dead end.** `role="tab"` tells the user that arrow keys move between tabs, `aria-expanded` tells them a control opens something, `aria-checked` tells them a state can be toggled. When the behaviour is not implemented, the user does the right thing and gets nothing — and now they distrust every announcement on the page. Wrong ARIA also *destroys* information that was already correct. `<button role="link">` throws away a working button's semantics. `role="presentation"` on a table strips the header relationships the browser had computed for free. Every override is a bet that your hand-written model is better than the platform's. ## Why the automated score is clean Rule engines such as axe-core test properties that are decidable from the DOM: is the role a real role, are required owned elements present, does every `aria-labelledby` ID resolve, is there a name on a control, is contrast sufficient. These are genuinely useful — and they are all *syntactic*. No static rule can answer the questions that matter here: does this `role="tablist"` actually implement roving-tabindex arrow navigation? Does `aria-expanded` flip when the panel opens? Does `aria-checked` match the visual state after the user acts? Does the accessible name still describe the control after the label was reworded? Truthfulness is a runtime, behavioural property. Treating a clean automated score as a pass is the specific management error that produces this codebase — the metric was optimised, the users were not. ## How to triage Work by *what stops a user completing a task*, not by rule count. **1. Operability.** Find controls nobody can reach or activate: interactive elements not in the tab order, custom widgets with no keyboard implementation, focus that is lost after an action. A control that cannot be operated is a hard blocker regardless of how it is announced. **2. Role truth.** Find declarations that promise behaviour the code does not implement — composite widget roles being the worst offenders, because each one implies a whole keyboard contract. The fix is usually to delete the role, not to implement it. **3. State accuracy.** Find states that are set once and never updated. A stale state is worse than an absent one because the user acts on it. **4. Names and descriptions.** Wrong or missing accessible names are real defects but rarely block a task outright once the control is operable and honestly typed. ## The cheapest fix is deletion For each finding, ask first whether a native element covers it. Replacing a div-plus-ARIA control with `<button>`, `<a href>`, `<input>`, or a real table removes several findings at once and removes the code that could drift back out of sync. It is a *subtraction* change: fewer attributes, fewer handlers, less to test. Reserve hand-built widget patterns for the shapes HTML genuinely lacks, and treat each one as an owned component with tests rather than markup someone typed inline. ## How you verify Behavioural checks, because the automated ones already pass: - **Keyboard-only pass.** Unplug the mouse and complete the product's top tasks. Every interactive element must be reachable, operable, and visibly focused. - **Screen-reader pass on the critical flows.** Listen for the mismatch between what is announced and what happens. - **Regression tests at the accessibility-tree level** — assert the computed role, name and state of key controls rather than asserting that an attribute string is present, so a refactor that changes the element is caught. ## Framing for the interview The sentence to land: ARIA is a promise to the user, and an unkept promise costs more than silence. Then show the triage order and the bias toward deleting ARIA rather than completing it. If you can add the organisational half — automated scores are a floor, not a definition of done — you are answering at the level the question is aimed at.

  • Which classes of accessibility defect do automated tools reliably catch, and which do they structurally miss?
    They catch decidable, DOM-visible facts: invalid role values, missing accessible names, unresolved `aria-labelledby` references, missing required child roles, contrast, duplicate IDs, missing `alt`. They structurally miss anything behavioural or semantic — whether a role matches the implemented interaction, whether a state updates, whether the name is *meaningful*, whether focus goes somewhere sensible, whether reading order matches visual order.
  • A team wants to keep its custom widget and finish the ARIA properly rather than move to native elements. How do you evaluate that?
    Price it. Finishing the pattern means implementing and testing its full keyboard contract on every supported browser and assistive technology, then keeping it correct through refactors — a component with an owner and tests, not markup. That is worth it when HTML has no equivalent element. When a native element exists, the same effort buys nothing that deletion would not.
  • How would you stop the automated score from being treated as the definition of done again?
    Change what the gate measures. Keep the linter as a floor, and add a keyboard-only pass to the definition of done for interactive work, accessibility-tree assertions in component tests, and periodic screen-reader testing of the top user flows. Report blocked tasks rather than rule counts, so the number tracks user impact instead of attribute hygiene.

saying these in an interview costs you the question

  • Treats a clean automated report as proof of accessibility
  • Wants to add more ARIA to fix broken ARIA
  • Believes assistive technology can detect a wrong role
  • Prioritises by rule count instead of blocked user tasks
  • Assumes screen readers fall back to native semantics when ARIA is wrong

context