Use real buttons and links

<button> for actions, <a> for navigation, never a <div> with onClick.

Web Interface Guidelinesvercel-labs · command.md
`<button>` for actions, `<a>`/`<Link>` for navigation (not `<div onClick>`)
Rule, Accessibility sectionView source ↗

From web-design-guidelines (Web Interface Guidelines).

Open an invoice

Click, Cmd-click or right-click; then Tab from Start here.

<div onClick>Bad
INV-1042Northwind Co$4,280.00
  • Tab reaches ituntested
  • Enter opens ituntested
  • Cmd/Ctrl+clickuntested
  • Middle-clickuntested
  • Link menuuntested

onClick={() => router.push(url)}
<a href>Good
INV-1042Northwind Co$4,280.00
  • Tab reaches ituntested
  • Enter opens ituntested
  • Cmd/Ctrl+clickuntested
  • Middle-clickuntested
  • Link menuuntested

<a href="/invoices/INV-1042">

Delete a note by keyboard

Tab to Delete, press Enter or Space, then patch the span.

<span onClick>Bad
Delete
Keyboard reachable
no
Screen reader hears
“Delete”

+0 lines
<button>Good
Keyboard reachable
yes
Screen reader hears
“Delete, button”

+0 lines
Patch the span

Name a field with a label

Click the words, not the boxes, then type an email.

<div> captionBad
Email for receipts
Send a copy to me

On focus: edit text

<div>Email</div><input>
<label for>Good

On focus: Email for receipts, edit text

<label for="email">Email</label>

Why it matters, pros and cons

Why it matters

Native elements bring focus, keys, a role and a URL; a div gets clicks.

Pros

  • Keyboard and screen reader support for free.
  • Links open in new tabs and copy.
  • Labels name fields and enlarge targets.

Cons

  • Native buttons need a one-time style reset.
  • No button inside a link; stretch one link instead.
  • Listbox, tree and grid still need ARIA patterns.