HTMLButtons (<button>)

Buttons (<button>)

The <button> element is the standard way to create a clickable control — inside a form, or anywhere on the page. It's more flexible than <input type="button"> because it can contain arbitrary HTML (icons, bold text, multiple lines) instead of only a plain string. The one detail that trips up almost every beginner: inside a <form>, a button's default behavior is to submit that form, whether you meant it to or not.

The Three Button Types

The type attribute controls what a button does when clicked. There are three values, and getting this right avoids one of the most common form bugs.

type

Behavior inside a <form>

submit (default!)

Submits the enclosing form — triggers validation and a page navigation/fetch.

reset

Resets every field in the form back to its initial value. Rarely a good idea in modern UX.

button

Does nothing on its own — just fires a click event for JavaScript to handle.

button-types.html

HTML
<form>
  <input type="text" name="query" />

  <!-- Submits the form -->
  <button type="submit">Search</button>

  <!-- Clears all fields -->
  <button type="reset">Clear</button>

  <!-- Does nothing until JS adds a listener -->
  <button type="button" id="toggle-filters">Show filters</button>
</form>
Why type="button" Matters

If you omit type entirely, a <button> inside a form defaults to submit. This is a very common source of bugs: a "show more" or "toggle" button meant to run a bit of JavaScript accidentally submits the whole form instead, reloading the page and losing all the user's input.

accidental-submit.html

HTML
<!-- BUG: clicking this reloads the page because the button -->
<!-- defaults to type="submit" inside the <form> -->
<form id="signup-form">
  <input type="email" name="email" required />
  <button onclick="showTooltip()">?</button>
  <button type="submit">Sign up</button>
</form>

<!-- FIX: be explicit -->
<form id="signup-form">
  <input type="email" name="email" required />
  <button type="button" onclick="showTooltip()">?</button>
  <button type="submit">Sign up</button>
</form>
Always be explicit inside forms
Any button whose job is *not* to submit or reset the form should carry type="button" explicitly. Don't rely on memorizing the default — it's easy to forget, and the failure mode (silent form submission) is confusing to debug.
<button> vs <input type="submit">

Both submit a form and both can be styled identically with CSS, so the choice mostly comes down to what content the button needs to hold.

<button>

<input type="submit">

Content

Any HTML — icons, <span>s, multiple text nodes

Plain text only, via the value attribute

Default type

submit (inside a form)

Always submit

Modern preference

Preferred — more flexible markup

Still valid, used less often today

button-vs-input.html

HTML
<!-- <button> can hold rich content -->
<button type="submit">
  <img src="/icons/cart.svg" alt="" width="16" height="16" />
  Add to Cart
</button>

<!-- <input type="submit"> is text-only -->
<input type="submit" value="Add to Cart" />
Disabled Buttons

A disabled button can't be clicked, focused, or included in form submission. It's commonly toggled with JavaScript — for example, disabling a submit button until required fields are filled in, or while an async request is in flight to prevent duplicate submissions.

disabled-button.html

HTML
<button type="submit" id="submit-btn" disabled>Submit</button>

<script>
  const form = document.querySelector('form');
  const submitBtn = document.getElementById('submit-btn');

  form.addEventListener('submit', () => {
    submitBtn.disabled = true;
    submitBtn.textContent = 'Submitting…';
  });
</script>
Disabled vs aria-disabled
A truly disabled button is skipped by keyboard tab order and invisible to some assistive technology interactions. When you need a button to look disabled but still be announced/focusable (e.g. to explain why it's inactive), consider aria-disabled="true" plus your own click-blocking logic instead.
The name/value Pair on Submit Buttons

A submit button can carry its own name and value, which get included in the form data — useful when a form has multiple submit buttons that should each trigger different behavior server-side (e.g. "Save Draft" vs "Publish").

named-submit-buttons.html

HTML
<form method="post" action="/posts/42">
  <textarea name="body"></textarea>
  <button type="submit" name="action" value="draft">Save Draft</button>
  <button type="submit" name="action" value="publish">Publish</button>
</form>

Only the button that was actually clicked sends its name=value pair — the server can branch on action to know which button the user pressed.

Styling Considerations
  • Buttons inherit weird default styling from the browser's user-agent stylesheet (borders, background, font) — most design systems reset it with something like appearance: none plus explicit border/background/font rules.

  • Keep a visible :focus-visible style — never remove focus outlines without replacing them, or keyboard users lose track of where they are.

  • Preserve a minimum touch target size (roughly 44×44px) for buttons that will be tapped on mobile.

  • Use real <button> elements instead of clickable <div>s or <span>s — buttons get keyboard support (Enter/Space activation), focus, and the correct accessibility role for free.

Icon-only buttons need an accessible name
If a button only contains an icon/image with no visible text, give it an aria-label (e.g. aria-label="Close dialog") so screen reader users know what it does.
Quick checklist
Always set type explicitly on every button. Default to type="button" for anything that isn't meant to submit or reset a form, and reserve the implicit submit default for the one button that should actually send the form.