Home HTML

The HTML <button> element

<button> is the right element for any user-action affordance. Three type values, optional form integration, and the 2024 commandfor / command attributes for declarative popover and dialog control.

What <button> is

<button> represents a control whose activation invokes an action. The action can be: submit a form, reset a form, run a JavaScript handler, or — since 2024 — invoke a command on another element declaratively.

<button type="submit">Save</button>
<button type="reset">Discard</button>
<button type="button">Toggle theme</button>

The default type is submit if the button is inside a <form>. This default catches authors out: a stray <button> inside a form submits on Enter from any text input, not the intended action. Always set type="button" for non-submitting buttons inside a form.

The three roles of <button>

typeWhat it does
submitSubmits the containing form. Default inside a form.
resetResets the containing form to initial values. Rare in modern UI.
buttonInert until JS attaches a handler. The “regular button”.

Outside a form, the default type is also submit per the spec, but with no form to submit it is effectively a no-op. Setting type="button" is still recommended for clarity.

The 2024 command and commandfor attributes

The HTML 2024 living standard added a declarative invocation primitive: a button can target another element on the page and issue a named command, no JavaScript required.

<button commandfor="my-dialog" command="show-modal">Open dialog</button>
<dialog id="my-dialog">…</dialog>

<button commandfor="my-popover" command="toggle-popover">More</button>
<div id="my-popover" popover>…</div>

The pre-defined commands are:

  • show-modal, close — for <dialog>.
  • show-popover, hide-popover, toggle-popover — for popover elements.
  • Custom commands prefixed with -- for author-defined behaviour.

Reached cross-engine availability in Chromium 135 (early 2025) and is in development in WebKit and Gecko. About 60% of new modal/popover code in greenfield projects uses the declarative form, per the State of HTML 2024 survey.

Form integration attributes

Inside a <form>, <button type="submit"> accepts attributes that override the form’s defaults just for that submit:

  • formaction — submit to a different URL.
  • formmethodget or post.
  • formenctype — different encoding.
  • formnovalidate — skip native validation.
  • formtarget — different target window.
  • name and value — pair sent only when this button submits.

The pattern is rare but powerful: a single form with separate “Save draft” and “Submit for review” buttons, each routing to a different endpoint, requires no JS.

Accessibility

<button> exposes role="button" and a default keyboard contract:

  • Enter and Space activate.
  • Tab focusable in document order.
  • Disabled buttons are removed from focus order; a button expressing inactive state without leaving focus order should use aria-disabled="true" instead.
  • Default :focus-visible outline (varies by engine).

For an icon-only button, provide an accessible name:

<button type="button" aria-label="Close">×</button>

The × glyph is announced as “multiplication” without the label.

Common pitfalls

  • <a href="#" onclick="..."> instead of <button>. Adds a spurious URL hash, breaks Cmd-click “open in new tab”, confuses screen readers.
  • <div role="button">. Misses the keyboard contract; needs manual tabindex, key handler, and disabled support.
  • <button> inside an <a> or vice versa. Invalid HTML and breaks AX exposure.
  • type omitted inside a form. Submits unintentionally.
  • Loading-state replaces button text but keeps the click handler enabled. Add disabled (or aria-disabled plus a guarded handler) to prevent double-submit.
  • <button> with mixed content (text + icon) and no aria-label works fine; the accessible name is the concatenated text. The problem is only icon-only buttons.

Cross-engine support

<button> and its three type values reached interop two decades ago. Form-association attributes (formaction etc.) reached interop in 2017. The 2024 command / commandfor attributes are Chromium 135+; WebKit and Gecko targets in 2025 per wpt.fyi/html/semantics/forms/the-button-element.

caniuse for <button command> reports about 75% global support in early 2025.

Further reading