Did you know that HTML links and buttons are not interchangeable?
One of my top annoyances with websites is when I want to open a link in a new tab and find out that I can't. Most of the time, this is because the thing I clicked on is not a link but a button or other element posing as one!
So here I am, asking you to please use links and buttons for their appropriate uses.
Be aware that I will use the words "link" and "anchor" to refer to the HTML <a>
element, and that none of this article has anything to do with the <link>
element.
TL;DR
In short:
- Anchors (links) are for navigating within the current document (page) or to another one.
- The dedicated "submit" and "reset" buttons are for specific form actions.
- Regular buttons are for (JavaScript) actions.
- Links can be styled to look like buttons and vice versa.
MDN definitions
As a primer, let us first look at the definition of anchor and button elements. I let the Mozilla Developer Network (MDN) do the heavy lifting and copied their definitions.
This is what MDN says about anchors:
The
<a>
HTML element (or anchor element), with itshref
attribute, creates a hyperlink to web pages, files, email addresses, locations in the same page, or anything else a URL can address.Content within each
<a>
should indicate the link's destination. If the href attribute is present, pressing the enter key while focused on the<a>
element will activate it.
And this is what MDN says about buttons:
The
<button>
HTML element is an interactive element activated by a user with a mouse, keyboard, finger, voice command, or other assistive technology. Once activated, it then performs an action, such as submitting a form or opening a dialog.By default, HTML buttons are presented in a style resembling the platform the user agent runs on, but you can change buttons' appearance with CSS.
As you can see, these elements have different uses and are not interchangeable.
(If you wish to go more technical, MDN also links to the official specifications on the given pages.)
Navigation versus actions
While there are always nuances, you can get away with this line for most of your use cases:
"Links are for navigation, and buttons are for actions."
Some examples of navigation:
- Link to another page within the current domain (
/hello-world/
); - Link to another domain (
https://example.com
); - Link to a specific element within the current page (
#footer
); - Set up a shortcut for sending emails (
mailto:[email protected]
); - Open a resource in another app using a non-HTTP URI scheme.
Examples of actions:
- Submit a form;
- Prefill user choices in a form;
- Open or close a dialog element;
- Expand or collapse a collection of elements;
- Add or remove an element from the page.
There are several perks to using either element as intended, for example:
- No need for JavaScript shims to mimic the other element's behaviors (actual JavaScript features aside).
- Use dedicated attributes out of the box for extra functionality, like anchor's
hreflang
andrel
. - Allow users to open a linked document in a new tab without losing their current position on the page.
- Improve your website's accessibility and usability for several access technologies, including but not limited to screen readers.
- Allow search engines to better index your content.
Example: Anchor instead of button
Instead of attempting to create a link with a button, use an anchor instead:
<!-- Bad: -->
<button onclick="location.href = 'https://example.com';">Hello world!</button>
<!-- Good: -->
<a href="https://example.com">Hello world!</a>
As a bonus, the latter implementation will not break when JavaScript crashes or has been disabled entirely.
Example: Button instead of anchor
Once you find yourself doing href="#"
, you are probably looking for a button:
<!-- Bad: -->
<a href="#" onclick="toggleTheThing()">Toggle the thing</a>
<!-- Good: -->
<button id="thing-toggler">Toggle the thing</button>
The related JavaScript would be something like:
// The method used in both situations:
const toggleTheThing = () => {
console.log('Implement toggle logic here.')
}
// Bind an event for the "good" option:
const thingToggler = document.getElementById('thing-toggler')
thingToggler.addEventListener('click', (event) => {
toggleTheThing()
})
Form buttons and the other one
Take note that there are two non-generic types of buttons meant for use in forms:
- A submit button (
<button type="submit">
) is used to submit a form. - The reset button (
<button type="reset">
) is used to reset form field values to their original state.
These two button types work without JavaScript and are generally good out of the box. You can also use JavaScript to intercept and adjust their default behavior.
Note: There are also the old input types that render as buttons (<input type="submit">
and <input type="reset">
). I do not use these as they are impractical to target with CSS and have fewer content options than button elements do.
With these two out of the way, one more type of button is left: the generic button: <button type="button">
.
You will want to use the generic button for most of your JavaScript magic. While you do not need to provide the type
attribute, I do this to clarify its intended behavior.
Typically, you will attach a click
event listener to these buttons, but you can also tie it to focus changes or key presses.
CSS can fix your styling issues
If you have a mix of HTML anchors and buttons, you can use CSS to make them look nearly identical.
(I say nearly because there are some subtle differences between the two elements. Most notable is that links typically have different cursors than buttons.)
While the actual styling of these elements is outside the scope of this article, I highly recommend looking for accessibility-related articles for both of them.
Wrap-up
Want to go somewhere? Use a link. Want to do something else? Use a button.
I recommend Adrian Roselli's article Links, Buttons, Submits, and Divs, Oh Hell, as a follow-up reading.
Appendix: Original toot
The toot that prompted this article:
For the love of all that is holy, can you all please start using
<a>
for navigation and<button>
for actions, not the other way around?Please don't make me turn this into a blog post.
Signed, someone who couldn't right-click to "open in a new tab" when it mattered.