Introduction
In my experience, developers often use anchors and buttons interchangeably for all sorts of tasks, like opening menus and modals, redirecting users, or even submitting forms.
For most users, this usually goes unnoticed and has little to no impact. But for people relying on assistive technologies, it makes a big difference. That small bit of semantic context is essential for understanding what action is being taken and what to expect next.
Semantics
Writing semantic HTML means using the right tool for the job and helping users avoid unexpected interactions with your product. When someone clicks a link, they expect to be redirected. Likewise, pressing a button signals that some kind of action will happen.
I dive deeper into semantic HTML in my article Championing Usability and Accessibility with HTML Semantics, but in short, using the right semantic elements is key to meeting user expectations and creating a more intuitive experience.
Using the anchor element
The anchor element (<a>
) is primarily used to link to another location, whether within the same document, a different webpage, or an external site.
However, it shouldn't be used to trigger functions or fire events. A common mistake is using an anchor with an empty fragment (#) tied to an event listener, like in the example below.
<a href="#" onclick="myFunction();">
This function should, instead, use a <button>
. However, this isn't a strict rule. Like most guidelines, there are exceptions. One example is a multi-level menu that expands or collapses, where using an anchor as a trigger can make sense.
<nav>
<ul>
<li><a href="">Category 1</a></li>
<li><a href="">Category 2</a></li>
<li><a href="" aria-expanded="false">Category 3</a>
<ul>
<li><a href="">Item 1</a></li>
<li><a href="">Item 2</a></li>
</ul>
</li>
<li><a href="">Category 4</a></li>
</ul>
</nav>
When used to link to a resource, an anchor's formatting can also vary depending on the target destination and the protocol being used.
<a href="#skip">Skip to content</a>
<a href="about.html">About me</a>
<a href="https://www.niquette.ca">Visit my website</a>
<a href="mailto:eric@niquette.ca">Send me an email</a>
Using the button element
The <button>
is an interactive element that activates when clicked, tapped, or triggered by another action. By itself, it doesn't perform any function. It needs to be connected to a programmed action, like toggling content or opening a modal window.
<button onclick="myFunction();">Run my function</button>
It's important not to use a button for redirecting users to another location at this is the intended purpose of the <a>
element.
The <button>
can also be set to a disabled state, preventing user interaction until certain conditions are met. This feature isn't available for anchors.
One common reason I've seen developers use an anchor instead of a button is the need for it to appear inline and blend in with other links. In these cases, CSS can easily style buttons to match seamlessly.
Using the button input type
The <input type="button">
element is designed for use within forms. Common functions include saving, submitting, clearing inputs, or handling other data-processing tasks.
<form>
<input type="submit" value="Submit">
<input type="reset" value="Reset">
</form>
It's best not to use input buttons outside of a form. However, a standard <button>
can be used within a form. By default, a <button>
inside a form behaves as a submit button unless its type
is explicitly set to button
.
<form>
<button>This button will submit the form</button>
<button type="button">But this button will not</button>
</form>
Accessibility considerations
Assistive technologies like screen readers recognize and announce button and anchor elements differently, which helps set user expectations. For example, most screen readers will announce the following button as: "More information. Button." This cues the user to expect a pop-up, tooltip, or informational window when the button is activated.
<button>More information</button>
In contrast, a screen reader will announce this anchor as: "Link. More information." This signals that clicking the link will redirect the user to another page with additional details.
<a href="about.html">More information</a>
Using the correct element ensures that users relying on assistive technologies have a clear understanding of what action will occur.
Working around limitations with roles
In some situations, you might not be able to swap out an element due to dependencies in scripts, stylesheets, or other restrictions. As a workaround, the role
attribute can override an element's default semantic meaning, changing how screen readers interpret it.
For example, this button will be read as a link by screen readers:
<button role="link">
Conversely, this link will be announced as a button:
<a role="button">
However, using the role
attribute is generally discouraged and should only be a last resort when no other solution is possible. It's best to use the correct semantic elements to maintain accessibility and clarity.
Activating buttons
Overriding a native element's semantic role
without replicating its full behavior, especially keyboard and ARIA support, can introduce significant accessibility barriers and confuse users.
When using the keyboard, buttons and anchors are activated differently. The <button>
element can be triggered using the Enter key or the Spacebar, while the <a>
element can only be activated with the Enter key.
Styling an anchor to look like a button might mislead users who expect the Spacebar to work. However, since this practice is so common and there's no perfect semantic alternative, the impact is usually minimal.
Anti-patterns
Even when functionality appears to work, misusing elements can lead to accessibility issues, confusing interactions, or increased development overhead. Below are a few anti-patterns to avoid when working with buttons, anchors, and inputs.
- Using a
<div>
or<span>
as a button or link: These elements are non-interactive by default. Making them behave like buttons requires extra scripting and ARIA roles, and they still lack built-in keyboard support unless explicitly added. - Triggering JavaScript actions with
<a href="#">
: Using an anchor to run a function instead of navigating misrepresents its purpose. This can confuse screen reader users and keyboard users who expect the link to lead somewhere. - Redirecting users with a
<button>
: Buttons are meant for triggering functions, not navigation. Using them to redirect breaks user expectations and can reduce clarity for assistive technology users. - Using
<input type="button">
outside of a form: This input type is designed for form tasks like submit or reset. Outside of a form, it's semantically weak and lacks the flexibility of a<button>
element. - Overusing the
role
attribute: Overriding native semantics withrole
should only be a fallback. If you assignrole="button"
to a link orrole="link"
to a button without full keyboard and ARIA support, the result is often less accessible than using the correct element in the first place.
Takeaways
Screen readers recognize the semantic difference between anchors and buttons, which helps users understand what to expect when interacting with them, whether that means navigating to a new location, submitting a form, or triggering an action within the page.
- Buttons are meant to trigger actions or initiate functions, like opening a modal or toggling content.
- Anchors are meant for navigation and should primarily be used for linking to other pages, sections, or URLs.
- Inputs are designed for form-related tasks.
- Use the
role
attribute cautiously and only when necessary. - When in doubt, choose the element that best matches the intended behavior, not just the desired visual or interactive style.