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
Tabkey. - Implicit submission
- Pressing
Enterin 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.
<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.
<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.
04A button outside the form
The form attribute takes the form's id. The button behaves exactly as if it were inside.
<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.
<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
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 novalue.) - 2
Let validation block a submit
Delete
formnovalidatefrom the draft button and changevalue="Tea"tovalue="". Run it. Neither button submits now, becausedrinkis required and empty (Topic 4.7). - 3
Try the keyboard
In the second example's preview,
Tabto Sign up and pressSpace, thenEnter. Both submit. Try to reach the div withTab: you can't.
Code & diagrams
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
Console
Nothing logged yet.Expected console output
Types: submit reset button
submitted by: save
submitted by: draft
after reset: Tea
Preview clicked: no submitPress `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
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: -1Break 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.
Break #2
A div as a button
Replace the Sign up button with <div onclick="signup.requestSubmit()">Sign up</div>.
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 thesubmitevent) is the button used, ornullwhen submitted byform.requestSubmit()with no argument.form.submit()is different: it skips validation and fires nosubmitevent, so preferrequestSubmit(). - ▸
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,Enterstill triggers it, which can surprise you. A form with several text fields and no submit button doesn't submit onEnterat all. - ▸
Since 2025, Chromium supports invoker commands (
commandandcommandforattributes) that let atype="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
The
<button>element has a **typeattribute with three values.submitsends the form (Topic 4.1).reset** puts every control in the form back to its starting value (thevalue,checkedandselectedattributes from the HTML). **button** does nothing on its own; it's for JavaScript actions such as "Show password" or "Add another row". - 2
The trap: a
<button>with **notypeinside a form is a submit button**. So a "Show password" button withouttype="button"submits the form and reloads the page. Always write thetypeon buttons inside forms. Outside any form, a button with no type does nothing on its own. - 3
<input type="submit" value="Send">(andtype="reset",type="button") is the older way. Its text comes fromvalueand 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 oraria-label="Close". - 4
A submit button can carry its own
nameandvalue, 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,formtargetandformnovalidate(skip validation, handy for "Save draft"). - 5
The **
formattribute** connects a control to a form by the form'sid, 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
Why not a
<div>with a click handler? A real<button>is focusable (reachable withTab), is activated byEnterandSpace, is announced as "button" by screen readers, works with voice control ("click Save"), can bedisabled, and submits forms. A<div>has none of that; rebuilding it needstabindex="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
What are the three button types, and which is the default inside a form?
Why should you use <button> instead of a clickable <div>?
How can one form have both "Publish" and "Save draft" buttons, and how does the server know which was pressed?
What does the form attribute on a button do?
Practice
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.
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
typeon buttons inside forms.I can explain what submit, reset and button types do.
I can use
name/valueandformnovalidateon submit buttons.I can connect a button outside a form with the
formattribute.I can explain why
<button>beats a clickable<div>.