Command Palette

Search for a command to run...

Hectal
PHASE 4Intermediate ~20 min· topic 6 of 8

Topic 4.6

Buttons

In one line

A <button> inside a form submits it unless you say otherwise: type="submit" sends, type="reset" restores the starting values and type="button" does nothing until JavaScript gives it a job. A real button comes with keyboard, focus and screen-reader support that a clickable <div> lacks.

Think of it like this

The buttons in a lift. Each one has a clear job, you can press it with a finger or find it by touch (raised numbers, braille), and it lights up to show it was pressed. A picture of a button painted on the wall looks the same but does nothing for someone who can't see it. A <div> styled like a button is the painted picture; <button> is the real one.

Words you'll meet

New words in this topic, in plain English. Come back here whenever one feels fuzzy.

button
The element for something you press to make an action happen.
type="submit"
A button that sends the form. It's the default for buttons inside a form.
type="reset"
A button that puts every field back to its starting value.
type="button"
A button that does nothing by itself; JavaScript gives it a job.
Submitter
The button that was used to submit the form.
form attribute
Links a control to a form by the form's id, even if the control is outside it.
Focusable
Can receive keyboard focus, so you can reach it with the Tab key.
Implicit submission
Pressing Enter in a text box submits the form, as if the submit button had been clicked.

Step by step

01One button, three types

Write the type every time. It documents what the button does and avoids the "button submitted my form" surprise.

index.htmlwhole filehtml
<form action="/profile" method="post">
  <label for="nick">Nickname</label>
  <input id="nick" name="nick" value="asha">
  <button type="submit">Save</button>
  <button type="reset">Undo changes</button>
  <button type="button" id="preview">Preview</button>
</form>

02Two submit buttons, two meanings

Both buttons submit, but the server can tell them apart because only the clicked one sends its name=value. The draft button also skips validation, so a half-finished form can be saved.

index.htmlwhole filehtml
<button type="submit" name="action" value="publish">Publish</button>
<button type="submit" name="action" value="draft" formnovalidate>Save draft</button>

03Pressing Enter

In a text box, Enter submits the form by "clicking" its first submit button (its default button). If that button is disabled, Enter does nothing. A form with no submit button still submits on Enter only if it has exactly one single-line text field.

Pressing Enterdiagram
Rendering diagram…

04A button outside the form

The form attribute takes the form's id. The button behaves exactly as if it were inside.

index.htmlwhole filehtml
<form id="signup" action="/signup" method="post">
  <label for="em">Email</label>
  <input id="em" name="email" type="email">
</form>

<footer>
  <button type="submit" form="signup">Sign up</button>
</footer>

05Icon buttons need words too

An icon is only a picture. Give the button a name screen readers can say, and hide the decorative icon from them.

index.htmlwhole filehtml
<button type="button" aria-label="Close">
  <svg aria-hidden="true" width="16" height="16" viewBox="0 0 16 16"><path d="M3 3l10 10M13 3L3 13" stroke="currentColor" stroke-width="2"/></svg>
</button>

Try it yourself

  1. 1

    Remove a type

    In the first example, delete type="button" from Preview. Predict the last two lines of output, then run. (Preview now submits: submitted by: followed by an empty value, because Preview has no value.)

  2. 2

    Let validation block a submit

    Delete formnovalidate from the draft button and change value="Tea" to value="". Run it. Neither button submits now, because drink is required and empty (Topic 4.7).

  3. 3

    Try the keyboard

    In the second example's preview, Tab to Sign up and press Space, then Enter. Both submit. Try to reach the div with Tab: you can't.

Code & diagrams

Submit, reset and plain buttons New tab

The Save button has no `type`, yet it reports `submit`: that is the default inside a form. Reset brought back the `value` attribute, `Tea`.

Preview

Press Run to see the page.

Console

Nothing logged yet.

Expected console output

Types: submit reset button
submitted by: save
submitted by: draft
after reset: Tea
Preview clicked: no submit
A real button vs a div New tab

Press `Tab` in the preview: focus visits the email box and both real buttons but skips the div. A `tabIndex` of -1 means "not in the Tab order".

Preview

Press Run to see the page.

Console

Nothing logged yet.

Expected console output

The button's form is: signup
signup submitted by a button
signup submitted by a input
button tabIndex: 0 | div tabIndex: -1

Break it on purpose

Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.

Break #1

A helper button without a type

Inside a form, add <button onclick="togglePassword()">Show password</button> with no type.

terminal
$ the page shows
── what you'll see ──
the page reloads (or the preview logs a form submission) every time you click Show password

Break #2

A div as a button

Replace the Sign up button with <div onclick="signup.requestSubmit()">Sign up</div>.

terminal
$ keyboard and screen reader
── what you'll see ──
Tab skips it, Enter does nothing, a screen reader reads "Sign up" as plain text

Myth vs fact

Myth

A button without a type does nothing until you add JavaScript.

Fact

Inside a form it's a submit button. Only outside forms, or with type="button", does it do nothing by default.

Myth

<input type="submit"> and <button> are identical.

Fact

Both submit, but <button> can hold HTML (icons, formatting) and is easier to style; input buttons only show their value text.

Myth

A reset button clears the form.

Fact

It restores the starting values from the HTML, which may not be empty. It's also rarely useful: people press it by mistake and lose their work.

Myth

Adding role="button" makes a div a button.

Fact

It only changes what screen readers announce. You'd still have to add focus (tabindex="0") and Enter/Space handling yourself.

Pro corner

Extra depth for experienced readers. New to this? Skip it for now and come back later.

  • ▸

    event.submitter (in the submit event) is the button used, or null when submitted by form.requestSubmit() with no argument. form.submit() is different: it skips validation and fires no submit event, so prefer requestSubmit().

  • ▸

    A disabled button can't be focused, so keyboard and screen-reader users may never learn it exists or why it's disabled. Many design systems keep it focusable with aria-disabled="true" and explain what's missing instead.

  • ▸

    Buttons in a form also count for implicit submission: if you hide the submit button with display: none, Enter still triggers it, which can surprise you. A form with several text fields and no submit button doesn't submit on Enter at all.

  • ▸

    Since 2025, Chromium supports invoker commands (command and commandfor attributes) that let a type="button" open a dialog or popover with no JavaScript; popovertarget (Topic 2.6) does the same for popovers and is Baseline 2024.

Remember this

  1. 1

    The <button> element has a **type attribute with three values. submit sends the form (Topic 4.1). reset** puts every control in the form back to its starting value (the value, checked and selected attributes from the HTML). **button** does nothing on its own; it's for JavaScript actions such as "Show password" or "Add another row".

  2. 2

    The trap: a <button> with **no type inside a form is a submit button**. So a "Show password" button without type="button" submits the form and reloads the page. Always write the type on buttons inside forms. Outside any form, a button with no type does nothing on its own.

  3. 3

    <input type="submit" value="Send"> (and type="reset", type="button") is the older way. Its text comes from value and it can't contain anything else. <button> can contain any inline content, such as an icon plus text, and is easier to style, so prefer it. An icon-only button still needs a name for screen readers: visually hidden text or aria-label="Close".

  4. 4

    A submit button can carry its own name and value, which are sent only when that button was used. That's how one form can have "Save" and "Save as draft" buttons. It can also override the form's settings for that one press: formaction, formmethod, formenctype, formtarget and formnovalidate (skip validation, handy for "Save draft").

  5. 5

    The **form attribute** connects a control to a form by the form's id, even when the control sits outside the <form> element: <button form="signup">. It's useful when the layout puts the button somewhere else, such as a sticky footer or a dialog's header.

  6. 6

    Why not a <div> with a click handler? A real <button> is focusable (reachable with Tab), is activated by Enter and Space, is announced as "button" by screen readers, works with voice control ("click Save"), can be disabled, and submits forms. A <div> has none of that; rebuilding it needs tabindex="0", role="button" and key handlers, and it's easy to get wrong. Use <a> for going somewhere (a URL) and <button> for doing something.

Explain it without notes

01

What are the three button types, and which is the default inside a form?

02

Why should you use <button> instead of a clickable <div>?

03

How can one form have both "Publish" and "Save draft" buttons, and how does the server know which was pressed?

04

What does the form attribute on a button do?

Practice

01

Make a form with a text input title, a Publish submit button, a Save draft submit button that skips validation, and a Cancel button that doesn't submit.

02

Write a button that sits outside a search form but submits it.

Trade-offs

  • ↔

    A reset button is easy to add but often destroys work by accident; most modern forms leave it out or replace it with a confirmed "Clear" action.

  • ↔

    Disabling the submit button until the form is valid stops bad submits but hides why it's blocked; leaving it enabled and showing errors on submit is usually clearer (Topic 4.8).

Done when you can

  • I always set type on buttons inside forms.

  • I can explain what submit, reset and button types do.

  • I can use name/value and formnovalidate on submit buttons.

  • I can connect a button outside a form with the form attribute.

  • I can explain why <button> beats a clickable <div>.