Overview
Links and buttons are the two primary interactive elements on the web, but they serve fundamentally different purposes. Links (<a>) navigate the user to a new URL or resource; buttons (<button>) trigger an action on the current page. Screen readers announce “link” vs. “button” to convey this distinction, and keyboard behavior differs: links activate on Enter only, while buttons activate on both Enter and Space. Mixing them up confuses assistive technology users and breaks expected keyboard interaction patterns.
WCAG Criteria:
- 1.3.1 Info and Relationships — information and relationships conveyed through presentation must be programmatically determinable
- 4.1.2 Name, Role, Value — interactive elements must expose their role and name
- 2.1.1 Keyboard — all functionality must be operable via keyboard
Key requirements:
- Use
<button>for actions (submit, save, toggle, delete, open dialog) - Use
<a href>for navigation (going to a new page or resource) - Never use
<div>or<span>as a substitute for either element - Links appear in screen reader link lists; buttons do not
- Links activate on Enter; buttons activate on Enter and Space
Div as Button vs. Semantic Button
Div as Button vs. Semantic Button
Inaccessible
<!-- div with onclick — not focusable, no role -->
<div class="btn" onclick="saveChanges()">Save Changes</div>Live Preview
Accessible
<!-- Semantic button — focusable, correct role, keyboard support -->
<button type="button" onclick="saveChanges()">Save Changes</button>Live Preview
What’s wrong with the div?
- No
buttonrole announced by screen readers — it’s just static text - Not focusable with the Tab key, so keyboard users cannot reach it
- Cannot be activated with Enter or Space
- No visible focus indicator
onclickonly fires on mouse click, not keyboard activation- Does not appear in screen reader form controls or interactive element lists
What the screen reader announces:
| Version | Announcement |
|---|---|
Inaccessible (<div>) | “Save Changes” (just text, no role, no interactivity) |
Accessible (<button>) | “Save Changes, button” |
Button for Navigation vs. Link
Button for Navigation vs. Link
Inaccessible
<!-- Button used for navigation — wrong semantics -->
<button onclick="window.location='/pricing'">View Pricing</button>Live Preview
Accessible
<!-- Link styled as a button — correct navigation semantics -->
<a href="/pricing" class="btn">View Pricing</a>Live Preview
What’s wrong with the button?
- Screen readers announce “View Pricing, button” — users expect an action, not navigation
- The element does not appear in the screen reader’s links list, which users rely on to scan for navigation options
- Users cannot right-click or Ctrl/Cmd+click to open in a new tab
- The browser’s built-in link behaviors (status bar URL preview, bookmarking, copy link address) are all lost
- If JavaScript fails to load, the button does nothing; a link still navigates
Why the distinction matters:
- Links change the URL. They navigate the user somewhere. Screen reader users can press a shortcut to list all links on a page and jump to one.
- Buttons perform an action in place (save, delete, toggle, open a dialog). They activate on both Enter and Space.
- When a button navigates, screen reader users are misled about what will happen — they expect an in-page action, not a page change.
What the screen reader announces:
| Version | Announcement |
|---|---|
Inaccessible (<button>) | “View Pricing, button” (implies action, not navigation) |
Accessible (<a>) | “View Pricing, link” (correctly implies navigation) |