Clear semantics are not optional—they are what let browsers, assistive technology and humans all make sense of a page. Choosing the right element (link or button) keeps your site compliant with WCAG 2.2 and, more importantly, keeps every user in control.
Why semantics matter
WCAG Success Criterion 1.3.1 (Info & Relationships) says that meaning must be conveyed programmatically, which you get “for free” when you use the correct native element.
WCAG Success Criterion 2.4.4 (Link Purpose) expects link text to make sense in context, something a button labelled “Learn more” can’t deliver when it actually jumps to a new page.
Links and buttons also map to different ARIA roles (
link
,button
) that screen-reader users rely on to build mental models of your UI.
Bottom line: get the element wrong and you break both keyboard flow and assistive-technology feedback.
Native roles & default behaviours
Element | Purpose | Default keyboard trigger | URL required? |
---|---|---|---|
| Navigation—moves the user to another document or an anchor within the current one | Enter | Yes ( |
| Action—submits a form, opens a dialog, toggles UI, etc. | Spacebar or Enter | No |
Users and screen readers expect these behaviours; overriding them forces you to re-implement focus, key bindings and announcement text yourself.
When to use a link
Use an <a>
element when the interaction navigates:
<!-- Primary navigation -->
<nav>
<a href="/pricing">Pricing</a>
<a href="/docs">Docs</a>
</nav>
<!-- “Back” pattern -->
<a href="previous-step.html" class="govuk-back-link">Back</a>
Moves to a new page or a different view (including single-page-app routes).
Scrolls to an in-page anchor (
href="#features"
).Downloads a file or opens email (
href="mailto:[email protected]"
).
GOV.UK reserves links for these cases—even its “Back” component is just an<a>
with styling.
When to use a button
Use a <button>
(or <input type="submit">
) when the interaction acts on the current page:
<!-- Form submission -->
<form>
<!-- inputs -->
<button type="submit">Save changes</button>
</form>
<!-- Open dialog -->
<button type="button" data-dialog="share">Share</button>
Typical actions:
Submit, reset or validate a form.
Show/hide or toggle content (accordion, hamburger menu).
Launch a modal, pop-over or toast.
Trigger Ajax requests that update the current view (e.g., “Load more”).
The GOV.UK Design System explicitly says:
“Use the button component to help users carry out an action like starting an application or saving their information.”
Keyboard expectations (why “role=button” on a link is risky)
Screen-reader users learn patterns: Enter activates a link; Space or Enter activates a button. When you restyle a link to look like a button without adding proper ARIA, keyboard handlers and focus indicators, you:
Hide the element from the Tab order unless you add
tabindex="0"
.Break Space-key activation, which many users rely on.
Force screen readers to announce “link” when users expect “button”.
If you must turn a non-button into a button (for legacy reasons), you have to replicate all of that behaviour yourself—usually more work than using the right element in the first place.
Grey areas & a quick decision flow
Does the user end up on a different URL?
Yes → Link.
No → Button.
Edge-case tips:
Single-page apps: internal route changes are still navigation—use a link component that updates history.
Accordion headings: if they only show/hide content, they’re actions → button (or
<summary>
).“Download” or “Print” buttons: downloading a file navigates to a new resource, so prefer
<a download>
.Anchor links: jump within page → link, because the address bar hash changes.
If you can’t answer “Will the URL change?” look at user expectation: “Am I going somewhere or doing something?”
Touch-target size (WCAG 2.5.8)
WCAG 2.2 adds minimum target spacing: 24 × 24 CSS px or a 24 px radius between interactive elements. That applies equally to links and buttons—if users can’t hit it, semantics won’t save you.
Accessible styling checklist
Keep focus outlines or replace them with equally visible custom styles.
Ensure a text/background contrast ratio ≥ 4.5 : 1 for normal text (WCAG 2.2 SC 1.4.3).
Use distinct hover, focus and visited states for links—visited colour helps orientation.
Don’t remove the underline from body-text links unless you add another persistently visible cue (e.g., bold colour).
Size touch targets generously (see above).
Testing workflow
Task | Tools |
---|---|
Keyboard-only navigation | Tab/Shift + Tab, Space, Enter |
Screen-reader labels | NVDA + Firefox, VoiceOver + Safari |
Colour contrast | WCAG contrast checkers |
Focus order | Accessibility tree viewers (Firefox DevTools, Chrome Accessibility pane) |
Mobile spacing | Browser dev-tools device emulation |
Key takeaways
Links navigate; buttons act. If the interaction changes the browser’s URL, reach for
<a>
. Otherwise, use<button>
.Native semantics give you correct ARIA roles, keyboard bindings and focus behaviour—no extra JavaScript required.
Styling alone does not change semantics; always start with the right element, then theme it.
Follow WCAG 2.2 for target size and clear link purpose, and test with keyboard and screen readers before shipping.
Use these rules and you’ll avoid the most common accessibility pitfall on the web—interactive elements that “look right” but act wrong. Your users (and future maintainers) will thank you.

Yucel is a digital product creator and content writer with a knack for full-stack development. He loves blending technical know-how with engaging storytelling to build practical, user-friendly solutions. When he's not coding or writing, you'll likely find him exploring new tech trends or getting inspired by nature.