Most "this button doesn't work" bugs are really a link pretending to be a button, or a button pretending to be a link.
Web HIG tip #3 (Quick #14, #16, #67, #68): Links navigate. Buttons act. Never make navigation behave like an action, and never build controls out of <div onClick>.
Why it matters
Users, browsers, and assistive tech all treat links and buttons differently:
- A link goes somewhere. It can be opened in a new tab, copied, bookmarked, and middle-clicked. Screen readers announce it as "link". Enter activates it.
- A button does something on this page: submit, save, open a dialog, toggle a panel. Screen readers announce it as "button". Enter and Space activate it.
When you mix them up, something quietly breaks:
- A
<button>that callsrouter.push()can't be opened in a new tab or copied - An
<a href="#">that deletes a row adds a junk history entry, and Space scrolls the page instead of firing - A
<div onClick>gets no focus, no keyboard support, and no role, so keyboard and screen-reader users can't use it at all
The rule of thumb
Ask: does this change the URL?
- Yes → use
<a href="..."> - No, it changes something here → use
<button type="button">(ortype="submit"inside a form)
<!-- Navigation: it's a link, even if it looks like a button -->
<a class="btn btn-primary" href="/projects/new">New project</a>
<!-- Action: it's a button, even if it looks like a link -->
<button type="button" class="link-style" onclick="openFilters()">Filters</button>
Styling is separate from semantics. A link can look like a button and a button can look like a link. Pick the element for behavior, then style it.
Do this instead
- Use native
<a>and<button>before reaching for ARIA roles - Never put click handlers on
<div>or<span>for interactive controls - If something navigates, give it a real
hrefso new tab, copy link, and Back all work - Keep the platform conventions people expect: links look like links, buttons look like buttons
Quick check for your app
Tab through one screen with the keyboard only. Every control should take focus, show a visible focus ring, and work with Enter (and Space for buttons). Then right-click each "link" and try "Open in new tab". Anything that fails one of those is the wrong element.
The Web HIG is a behavioral contract for how the web should behave, not a component library. Design systems define look. The Web HIG defines behave.
- Docs: https://frozonfreak.github.io/webhig/
- Quick Reference: https://github.com/frozonfreak/webhig/blob/main/HIG-QUICK.md
- Tip discussion: https://github.com/frozonfreak/webhig/discussions/11
- Repo: https://github.com/frozonfreak/webhig
Top comments (0)