skip to content

What actually changes when you write `<a href="/settings" role="button">Settings</a>`, and what stays exactly the same?

level: middleimportance: should knowfreq 50%

answer

  1. announced role only
  2. the href still wins
  3. Enter yes, Space no
  4. navigation versus action

basics

~20 s

Only the announced role changes. ARIA writes to the accessibility tree, so a screen reader says "button", but the element still navigates on activation, still responds to Enter and not Space, and still offers link context menus.

solid answer

~50 s

An explicit `role` overrides the element's implicit role in the accessibility tree — nothing else. Assistive technology now announces "Settings, button" and includes it when the user lists buttons instead of links. Everything the browser does stays untouched: activating it navigates to `/settings`, Enter activates it while Space does not (Space scrolls, because that is link behaviour), the status bar shows the URL, and the context menu still offers "open in new tab". So you have created a mismatch — the user is told "button" and gets link behaviour, and if they press Space nothing happens. The rule of thumb underneath is simple: if it changes the URL it is a link, if it acts on the current page it is a button. Pick the element that matches the behaviour instead of relabelling the wrong one.

code

html · 9 lines
html
<script>
  function openSettingsPanel() { document.body.classList.toggle('settings-open'); }
</script>

<!-- changes the URL: it is a link, style it however you like -->
<a href="/settings" class="btn">Settings</a>

<!-- acts on the current page: it is a button, Enter and Space both work -->
<button type="button" class="btn" onclick="openSettingsPanel()">Settings</button>

go deeper

for a junior

Know that a link navigates and a button acts, and that adding a role changes only what is announced. Do not use role to convert one into the other.

for a middle

Explain that explicit roles override the implicit role in the accessibility tree and nothing else, and give the concrete mismatch: announced as a button, activates on Enter only, Space scrolls, link affordances remain.

for a senior

Be able to spot the pattern in review and explain the user-visible failure rather than citing a rule, including why <a href="#"> handlers and href-less anchors are the same defect in different clothing.

for a principal

Decide the boundary once for the whole system — which primitive renders a navigation and which renders an action — so that link-versus-button is a property of the component API rather than a judgment each engineer re-makes at every call site.

## What an explicit role does Every HTML element maps to an implicit role in the **accessibility tree** — the structure the browser exposes to screen readers, voice control and other assistive technology. `<a href>` maps to `link`, `<button>` to `button`, `<div>` to a generic role. Writing `role="button"` replaces the implicit role for that node. That replacement is total but narrow. It is total in that assistive technology now believes the element is a button: it is announced as one, it appears in the screen reader's list of buttons and disappears from the list of links, and the user's mental model of how it should respond is set accordingly. It is narrow in that the accessibility tree is the *only* thing that changed. ## What did not change The browser's own behaviour is driven by the element and its attributes, not by ARIA: - **Activation still navigates.** The `href` is what makes a link navigate; the role does not intercept it. - **Keyboard behaviour is still the link's.** Links activate on Enter. Buttons activate on Enter *and* Space. On this element, Space does what it does on any non-button focusable element — scrolls the page. A user who trusts the "button" announcement and presses Space gets a scroll, not an action. - **Browser affordances stay.** The URL appears in the status bar on hover, the context menu offers "open in new tab" and "copy link address", and middle-click opens a new tab. - **Styling is unaffected.** CSS does not read the accessibility tree; `role` only participates in styling through an attribute selector you write yourself. - **The element is still a link to the rest of the platform** — history, referrer behaviour, and how the page is crawled are all `href` concerns. So the net effect of the attribute alone is a lie plus a missing key handler. ## If you insist on the pattern, you owe the contract ARIA authoring guidance is explicit that a link given `role="button"` must be made to behave like a button, which in practice means adding a Space handler that activates it and cancels the default scroll: ```html <a href="/settings" role="button" onkeydown="if (event.key === ' ') { event.preventDefault(); this.click(); }">Settings</a> ``` Even then the browser affordances remain wrong — "open in new tab" on something the user was told is a button is incoherent. That is the tell that the markup is the wrong shape, not that it needs another attribute. ## Choosing the element instead The decision rule interviewers want to hear: **navigation is a link, action is a button.** If activating the control results in a different URL — a new page, a route change, a jump within the document — use `<a href>`. If it operates on the current page — open a panel, submit, delete, toggle — use `<button type="button">`. Styling is not part of this decision; both elements are fully stylable, and a link can be made to look like a button without ever touching `role`. Two related anti-patterns follow the same logic. `<a>` with no `href` is not a link at all: it has no `link` role and is not focusable, so `<a onclick="…">` is the div-button bug wearing an anchor tag. And `<a href="#">` with a click handler that cancels the default is a link whose destination is a fiction — it pollutes history and breaks middle-click, when a button was wanted all along. ## The override rule that surprises people Explicit roles win over implicit ones in general, but not unconditionally. The presentational roles `role="presentation"` and its synonym `role="none"`, which ask the browser to strip an element's semantics, are **ignored** when the element is focusable or carries a global ARIA attribute — a conflict-resolution rule in the ARIA specification. So `<button role="presentation">` remains a button in the accessibility tree, because silently hiding a focusable control from assistive technology would strand keyboard users on an element that reports nothing. It is a useful thing to know precisely because it shows the platform actively defending against ARIA that would break the user. ## What to say Lead with the one-liner — ARIA changes the accessibility tree, never behaviour — then give the concrete consequence: announced as a button, still activates on Enter only, still navigates, still shows link affordances. Close with the navigation-versus-action rule.

  • What happens if you put `role="presentation"` on a focusable element such as a `<button>`?
    It is ignored. The ARIA specification resolves the conflict in the user's favour: a presentational role does not apply to an element that is focusable or carries a global ARIA attribute, because a focusable node with no exposed role would strand keyboard and screen-reader users. The button keeps its role. The lesson is that you cannot hide an interactive element from assistive technology by relabelling it.
  • Is `<a href="#">` with a click handler an acceptable way to build an in-page action?
    No. It is a link with a fictional destination: it adds a history entry or jumps to the top, middle-click opens a useless tab, and the user is told "link" for something that acts on the page. It also requires cancelling the default on every activation path. Use `<button type="button">` — that is what it is.
  • Does `<a>` without an `href` still count as a link?
    No. Without `href` the element has no `link` role and is not focusable, so it is functionally a `<span>` with an underline. Attaching a click handler to it recreates the div-button problem exactly: mouse users can operate it and nobody else can.

saying these in an interview costs you the question

  • Believes role="button" makes Space activate the link
  • Thinks ARIA can override what an element does, not just how it is reported
  • Uses role to fix a link that should have been a button
  • Says a link and a button are interchangeable if styled the same
  • Assumes role="presentation" reliably hides any element from assistive technology

context