Stop Using Links as Buttons: When to Use a, button, or input type="button"
a, button, and input type="button" can all look like buttons, but they differ in semantics, keyboard interaction, form behavior, styling flexibility, and accessibility. Learn which HTML element to use and when.
As web developers, we are all familiar with the a, button, and input HTML elements. CSS can make all three look like buttons, but a similar appearance does not mean they serve the same purpose.
Their differences go beyond whether they can contain an image. They also differ in where their content comes from, their default behavior, HTML semantics, CSS flexibility, and accessibility.
Start with the most important rule:
Use
ato go somewhere. Usebuttonto do something.
An input type="button" can also perform an action, but it offers less flexibility in content and styling. Unless a project has a specific constraint, button is usually the better choice for new code.
Quick Comparison
| Element | Primary Semantics | Content Source | Default Behavior | Can Contain HTML Elements? |
|---|---|---|---|---|
a | Navigate to another URL or document location | Content between the opening and closing tags | Navigate to its href | Yes, but it cannot contain other interactive elements |
button | Perform an action | Content between the opening and closing tags | May submit a form when used inside one | Yes: text, images, SVG, span, and other phrasing content |
input type="button" | Perform an action | The value attribute | No default action | No; it is a void element |
Difference 1: The HTML Content They Can Contain
The most obvious difference is that a button can use HTML content to build its label, while an input type="button" can display only a plain-text label.
1
2
3
4
<button type="button">
<img src="save.svg" alt="">
<span>Save</span>
</button>
A button can contain text, images, span, strong, or SVG elements. This makes it suitable for icon buttons and labels with multiple visual styles.
Strictly speaking, however, a button cannot contain “any HTML.” Its content is primarily phrasing content, and it cannot contain interactive elements such as a, another button, or input.
1
2
3
4
5
<!-- Invalid: do not put an interactive element inside a button -->
<button type="button">
Save
<a href="/help">Help</a>
</button>
An input, on the other hand, is a void element. It has no closing tag and cannot contain child elements:
1
<input type="button" value="Save">
The following markup does not conform to the HTML specification:
1
2
3
4
5
<!-- Invalid: an input cannot contain child elements -->
<input type="button">
<img src="save.svg" alt="">
Save
</input>
One commonly overlooked detail is that a is not limited to text either. It can also contain images, span, strong, SVG, or even form an entire clickable card:
1
2
3
4
5
6
7
<a href="/settings" class="link-card">
<img src="settings.svg" alt="">
<span>
<strong>System Settings</strong>
<small>Manage your account and notifications</small>
</span>
</a>
The a element uses a transparent content model, so the content it may contain also depends on its surrounding context. However, it cannot contain another a or interactive elements such as button and input, and its descendants cannot have a tabindex attribute.
Difference 2: Where the Displayed Content Comes From
The visible content of a and button comes from the DOM content between their opening and closing tags:
1
2
<a href="/settings">System Settings</a>
<button type="button">Save</button>
Their labels can also be composed of multiple child elements:
1
2
3
4
<button type="button">
<svg aria-hidden="true"><!-- icon --></svg>
<span>Save Changes</span>
</button>
In contrast, the text displayed by input type="button" comes from its value attribute:
1
<input type="button" value="Save Changes">
That also changes how their labels are updated with JavaScript:
1
2
document.querySelector("button").textContent = "Processing";
document.querySelector('input[type="button"]').value = "Processing";
This is one reason why button is easier to extend: its label is DOM content, so icons, text, loading states, and other visual elements can be updated independently. An input has only its text-based value.
Difference 3: Their Default Behavior
Browsers provide different default behavior when these elements are activated.
The Default Behavior of a Is Navigation
An a with an href is a hyperlink. Activating it navigates to another page, website, file, or location in the same document:
1
2
3
<a href="/settings">Go to Settings</a>
<a href="#comments">View Comments</a>
<a href="/report.pdf" download>Download Report</a>
A button May Submit a Form
Inside a form, a button without an explicit type will usually become a submit button. A button intended only to open a dialog or preview some content may therefore submit the form by accident.
1
2
3
4
5
6
7
8
9
10
<form>
<!-- Perform an ordinary action without submitting the form -->
<button type="button">Preview</button>
<!-- Submit the form -->
<button type="submit">Save</button>
<!-- Reset the form; less common in practice -->
<button type="reset">Reset</button>
</form>
Even when a button is not currently inside a form, explicitly writing type="button" prevents surprises if the DOM structure changes later.
input type=”button” Has No Default Action
An input type="button" does not navigate or submit a form by itself. It usually needs JavaScript to do something:
1
<input type="button" value="Open Dialog" onclick="openDialog()">
Do not confuse it with input type="submit":
1
2
3
4
5
<!-- An ordinary button with no default action -->
<input type="button" value="Preview">
<!-- Submit the form -->
<input type="submit" value="Save">
Difference 4: Their HTML Semantics
The most important difference between these elements is not how they look, but what they communicate to the browser.
a Means “Go Somewhere”
If activation changes the URL, opens another page, moves to a different location in a document, or downloads a file, use an a with an href.
Links also provide native browser capabilities: users can open them in a new tab, copy their URLs, and search engines can understand the relationships between pages.
Do not use an a without an href as a fake button:
1
2
3
4
5
<!-- Not recommended -->
<a onclick="openDialog()">Open Dialog</a>
<!-- Correct semantics -->
<button type="button" onclick="openDialog()">Open Dialog</button>
Using href="#" is not a good substitute either. It still represents navigation and may change the URL or jump the page back to the top.
button and input type=”button” Mean “Perform an Action”
Opening a dialog, toggling a menu, adding an item to a cart, and saving data are all actions on the current page, so they should use buttons.
Both button and input type="button" can semantically represent a button. However, button supports richer content and is generally more practical in new code. An input type="button" remains useful in legacy systems, tool-generated forms, or simple cases that require only a text label.
Conversely, using a button with JavaScript to simulate navigation is also discouraged. It removes native link features such as opening a destination in a new tab or copying its address.
In one sentence:
Link goes somewhere. Button does something.
Difference 5: CSS and Layout Flexibility
CSS can make all three elements look nearly identical, but their browser defaults and internal styling flexibility still differ.
An a is normally displayed as an inline text link, while button and input receive native form-control styles from the browser or operating system. In practice, a shared style often normalizes their font, border, background, and spacing:
1
2
3
4
5
6
7
8
9
10
11
12
13
.button {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
padding: 0.5rem 1rem;
border: 1px solid transparent;
border-radius: 0.375rem;
font: inherit;
color: inherit;
text-decoration: none;
cursor: pointer;
}
1
2
3
<a class="button" href="/settings">Go to Settings</a>
<button class="button" type="button">Save</button>
<input class="button" type="button" value="Preview">
The real difference appears in their internal layout. Both a and button can contain separate elements for icons and text, which can then be arranged with Flexbox, Grid, or individual classes. An input has no child elements, so only the control itself can be styled; its internal text and icons cannot be laid out independently.
If a design needs an icon, loading spinner, two lines of text, or other compound content, button is usually a better choice than input type="button".
Difference 6: Accessibility
When native HTML elements are used correctly, the browser provides the appropriate role, focus behavior, and keyboard interaction:
- An
awith anhrefis exposed as a link and is typically activated with Enter. buttonandinput type="button"are exposed as buttons and are typically activated with Enter or Space.buttonandinputsupport the nativedisabledattribute.adoes not have adisabledattribute.
1
2
<button type="button" disabled>Processing</button>
<input type="button" value="Processing" disabled>
Adding aria-disabled="true" to an a only communicates the disabled state through the accessibility tree. It does not automatically prevent navigation or click events. If a control is fundamentally an action that can be disabled, it is usually better represented by a button in the first place.
Icon Buttons Still Need an Understandable Name
An icon-only button without visible text should have a clear accessible name:
1
2
3
<button type="button" aria-label="Close dialog">
<svg aria-hidden="true"><!-- close icon --></svg>
</button>
If an icon is accompanied by text that already explains the action, a decorative image can use an empty alt value so that screen readers do not announce the same information twice:
1
2
3
4
<button type="button">
<img src="save.svg" alt="">
Save
</button>
Do not simulate a button with a div or span. Otherwise, you must manually recreate focus behavior, keyboard events, and ARIA semantics—and it is easy to miss something.
1
2
3
4
5
<!-- Not recommended -->
<div class="button" onclick="save()">Save</div>
<!-- Recommended -->
<button type="button" onclick="save()">Save</button>
When a native HTML element already solves the problem, there is no need to reinvent a less usable button.
Which One Should You Use?
Use this checklist to decide:
- Does activation change the current URL, navigate to another page, or download a resource? Use
a href="...". - Does it perform an action on the current page? Use
button. - Does the button submit a form? Use
button type="submit". - Is it an ordinary action that should not submit a form? Use
button type="button". - Are you constrained by a legacy system or need only a plain-text form control? Only then consider
input type="button".
Choose the correct HTML semantics first, then use CSS to control the appearance. This makes the code easier to maintain and allows keyboards, assistive technologies, and search engines to understand the page correctly.