button Element vs input type="button"
Both create clickable buttons, but the <button> element is far more powerful because it is a container element β it can hold HTML content including text, icons, images, and spans. The <input type="button"> is a self-closing void element that can only display plain text via its value attribute.
<!-- input type="button" β plain text only, no HTML inside -->
<input type="button" value="Click me">
<!-- button element β can contain HTML content -->
<button type="button">Click me</button>
<!-- button with icon + text -->
<button type="button">
<svg aria-hidden="true" width="16" height="16">β¦</svg>
Download PDF
</button>
<!-- button with styled spans -->
<button type="button">
<span class="btn-icon">β
</span>
<span class="btn-text">Add to favourites</span>
</button>
<button> over <input type="button">. The <button> element is more flexible, easier to style, and supports rich content. The <input> form is a legacy approach.
button vs input β Comparison
| Feature | <button> | <input type="button"> |
|---|---|---|
| Can contain HTML? | Yes β icons, spans, images | No β plain text only (via value) |
| Self-closing? | No β needs closing tag | Yes β void element |
| Default type in form? | submit | button (no form action) |
| CSS pseudo-elements? | Yes β ::before, ::after | Limited |
| Recommended? | Yes | Legacy; avoid |
Button Types: submit, reset, button
The type attribute on a <button> controls what happens when it is clicked inside a form.
type="submit" β Submits the Form
This is the default type when a <button> is inside a <form> with no type attribute specified. Clicking it triggers form validation and submits the form.
<form action="/checkout" method="POST">
<!-- β¦ form fields β¦ -->
<!-- Explicitly typed as submit -->
<button type="submit">Place order</button>
<!-- Equivalent β default inside form is submit -->
<button>Place order</button>
</form>
type="button" to a non-submit button inside a form, it defaults to type="submit" and submits the form unexpectedly. Be explicit to avoid hard-to-debug bugs.
type="reset" β Clears All Fields
A reset button restores all fields in the form to their initial default values. It does not submit the form.
<form action="/search" method="GET">
<label for="kw">Keyword</label>
<input type="text" id="kw" name="q" value="">
<button type="submit">Search</button>
<button type="reset">Clear</button>
</form>
type="button" β No Default Action
A type="button" button does nothing by itself. It is entirely JavaScript-controlled. Use it for UI actions that do not submit a form β opening modals, toggling menus, incrementing counters.
<!-- Opens a modal when clicked -->
<button type="button" id="open-modal">View preview</button>
<!-- Increases quantity counter -->
<button type="button" onclick="increment()">+</button>
<span id="count">0</span>
<button type="button" onclick="decrement()">β</button>
Disabled Buttons
The disabled attribute prevents the button from being clicked and applies a greyed-out visual style. Disabled buttons are excluded from tab-order and not submitted with the form.
<!-- Permanently disabled -->
<button type="submit" disabled>Submit</button>
<!-- Disabled until checkbox is ticked -->
<form>
<label>
<input type="checkbox" id="agree-chk">
I agree to the terms
</label>
<button type="submit" id="agree-btn" disabled>Continue</button>
</form>
const chk = document.getElementById('agree-chk');
const btn = document.getElementById('agree-btn');
chk.addEventListener('change', function() {
btn.disabled = !this.checked;
});
disabled removes the element from tab focus completely. If you want the button reachable by keyboard (so screen readers can announce why it is inactive), use aria-disabled="true" with CSS styles and JavaScript to prevent click action β do not use the disabled HTML attribute.
Button Content β HTML Inside button
Unlike <input type="submit">, a <button> can contain rich content. This is its primary advantage.
<!-- Text with loading spinner (toggled by JavaScript) -->
<button type="submit" id="save-btn">
<span class="spinner" aria-hidden="true"></span>
<span>Save changes</span>
</button>
<!-- Icon-only button (needs aria-label) -->
<button type="button" aria-label="Close dialog">
<svg aria-hidden="true" focusable="false" width="20" height="20"
viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</button>
<!-- Button that looks like a link -->
<button type="button" class="btn-link">Learn more</button>
Accessibility β Clear, Descriptive Button Text
Accessible buttons need a clear, descriptive name that tells users what will happen when they activate the button. Screen readers read the accessible name aloud.
<!-- β
Good: describes the action clearly -->
<button type="submit">Create account</button>
<button type="button">Delete file "report.pdf"</button>
<button type="button">Add Python course to cart</button>
<!-- β Bad: vague, non-descriptive -->
<button type="submit">Click here</button>
<button type="submit">Submit</button>
<button type="button">OK</button>
<!-- Icon-only button: aria-label provides the accessible name -->
<button type="button" aria-label="Search">
π
</button>
<!-- Icon + visible text: aria-hidden on icon to avoid redundancy -->
<button type="button">
<span aria-hidden="true">ποΈ</span>
Delete selected files
</button>
π Summary
- Use
<button>over<input type="button">β it supports HTML content and is easier to style. type="submit"β submits the form; this is the default inside a form element.type="reset"β clears all fields to their default values; use sparingly.type="button"β no default action; must be paired with JavaScript for any behaviour.disabledβ greys out the button and prevents clicks; button is excluded from form submission and tab focus.- Always provide a clear, descriptive accessible name β either visible text or
aria-labelfor icon-only buttons. - Add
aria-hidden="true"to decorative icons inside buttons to prevent screen readers from reading icon names.
Frequently Asked Questions
Why does my button submit the form when I don't want it to?
A <button> inside a <form> with no explicit type defaults to type="submit". Add type="button" to any button that should not trigger form submission β for example, a "Preview" button, a modal trigger, or a quantity stepper inside a checkout form.
Can I submit a form with a button that is outside the form element?
Yes. Use the form attribute on the button to link it to a form by that form's id. This is useful for placing a submit button in a toolbar or footer far from the actual form element in the DOM: <button type="submit" form="checkout-form">Place order</button>.
What is the difference between disabled and readonly on a button?
Buttons do not support readonly β that attribute only applies to input and textarea. For buttons, disabled is the only built-in way to prevent interaction. If you need the button to remain focusable but appear inactive, use aria-disabled="true" plus CSS and a JavaScript click handler that does nothing.
Should I use a button or an anchor tag for navigation?
Use <a href="β¦"> for navigation (changing the URL, opening a link). Use <button> for actions (submitting a form, opening a modal, toggling a menu, incrementing a value). The distinction matters for accessibility β screen readers announce anchors as "link" and buttons as "button", setting user expectations. Never use a <div> or <span> as a clickable button.