How to make a button in HTML
A button is the <button> element. The content between the tags is what the user sees, and type="button" says it runs your script rather than sending a form. Click it in the preview:
That is all a working button needs: a label, a type, and something that listens for click. The browser makes it keyboard focusable and activates it with Enter or Space, so keyboard users get it for free. A <div> with a click handler gets none of that.
You may also see onclick="..." written straight in the tag. It works, but addEventListener keeps the script out of the markup and lets several listeners share one button.
The three button types
The type attribute decides what a button does when it is pressed.
type | What it does | Use it for |
|---|---|---|
submit | Sends the form it belongs to. This is the default. | The main action of a form |
button | Nothing on its own; your JavaScript decides | Toggles, dialogs, counters, anything scripted |
reset | Puts every field of the form back to its initial value | Rarely; users hit it by mistake |
Type something, then try each button. The preview does not leave the page when the form submits; it shows the data the form would have sent.
Reset restores the value written in the HTML (Ada), not an empty field. And if you delete type="button" from Uppercase, it becomes a submit button: it uppercases the name and then submits the form.
HTML submit button: sending a name and value
A submit button can carry its own name and value. They are sent with the form only when that button is the one that submitted it, so two buttons can share one form and tell the server which action was chosen:
Press Publish and the form sends title=My first post and action=publish. Clear the title and press either button: required stops the submit and the browser shows its own message. Pressing Enter inside the text field also submits, and the browser treats it as a press of the first submit button, so it sends action=draft.
Submit buttons also accept attributes that override the form for that one button: formaction (a different URL), formmethod, formtarget, and formnovalidate, which skips validation. formnovalidate is the usual choice for a "Save draft" button that should work while required fields are still empty.
A button placed outside its form can still submit it with the form attribute, which takes the form's id: <button type="submit" form="signup">Sign up</button>.
Disabled buttons
The disabled attribute turns a button off. A disabled button ignores clicks, is skipped by Tab, and is not sent with the form. Browsers also grey it out. A common pattern is to keep the submit button disabled until a condition is met:
In JavaScript, button.disabled is a boolean property: set it to true or false. In HTML, the attribute's presence is what counts, so disabled="false" still disables the button.
A disabled button gives no reason why it is disabled, and keyboard and screen reader users moving with Tab never land on it. When the reason is not obvious, say it in text next to the button, or leave the button enabled and show an error message when it is pressed.
Styling a button with CSS
Browsers draw buttons with their own font, border and background. Setting a few properties replaces all of that. Keep a visible focus style: it is how keyboard users see where they are.
What each rule is for:
font: inheritmakes the button use the page's font. Without it, buttons use the browser's own smaller form font (13.33px in Chrome and Firefox).cursor: pointershows the hand cursor. Buttons show the normal arrow by default.:hover,:activeand:focus-visiblestyle the pointer, press and keyboard states.:focus-visibleshows the ring for keyboard focus but not after a mouse click, so you do not have to removeoutlineto avoid it.:disabledtargets buttons with thedisabledattribute.
Press Tab in the preview to see the amber focus ring move between the first two buttons. The disabled one is skipped. (On a Mac, Safari and Firefox only Tab to buttons when keyboard navigation is turned on in the system settings; in Safari, Option+Tab works without it.) For the full list of states, see CSS hover.
Buttons with icons
Because <button> can hold HTML, an icon goes inside it next to the text. An icon-only button has no text for screen readers to announce, so give it an aria-label:
aria-hidden="true" on the SVG keeps it out of the accessibility tree, so the first button is announced as "Add item, button" and the second as "Delete, button".
button vs input type="submit"
<input type="submit"> is the older way to write a submit button. Both send the form the same way; the difference is what they can contain.
<input type="submit" value="Send"> <!-- label comes from value, text only -->
<button type="submit">Send</button> <!-- label is the content, HTML allowed -->
<button> | <input type="submit"> | |
|---|---|---|
| Label | Content between the tags | The value attribute |
| Can contain icons or markup | Yes | No |
| Closing tag | Required | None (void element) |
| Default type | submit | Always submit |
Use <button>. The only reason to keep <input type="submit"> is existing CSS or JavaScript that selects it. There are also <input type="button"> and <input type="reset">, the same idea for the other two types.
Button or link?
A button does something on the current page: submits, opens, toggles, deletes. A link goes to another URL. If clicking it changes the address bar, it should be an <a href>, styled like a button if the design calls for it. That pattern, and why a button inside a link is invalid, is covered in HTML button link.
Accessibility
- Use a real
<button>. It is focusable, works with Enter and Space, and is announced as a button. Rebuilding that on a<div>needsrole,tabindexand key handlers, and is usually still incomplete. - Every button needs a name: its text, or
aria-labelwhen it only has an icon. - Keep a visible focus style.
outline: nonewith no replacement leaves keyboard users lost. - Make the target big enough to hit. WCAG 2.2 asks for at least 24 by 24 CSS pixels; padding like the styled example above gives about 40 pixels of height.
- For a toggle, add
aria-pressed="true"or"false"and update it when the state changes.
Common mistakes
- A button in a form with no
type. It submits the form. Writetype="button"on every button that is not meant to submit. - Wrapping a button in a link,
<a href="/x"><button>Go</button></a>. It is invalid HTML and behaves differently across browsers. Use one element: a link styled as a button. - Using
<div onclick>as a button. It cannot be reached with the keyboard. - Removing the focus outline without adding a
:focus-visiblestyle. - Writing
disabled="false"and expecting an enabled button. Remove the attribute instead. - Forgetting
font: inheritand wondering why buttons use a different font from the rest of the page.
Frequently Asked Questions
How do you make a button in HTML?
Write <button type="button">Click me</button>. The text between the tags is the label. Add a click listener in JavaScript to make it do something, or put it inside a <form> with type="submit" to send the form.
What is the default type of an HTML button?
submit. A <button> with no type attribute inside a form submits that form when clicked, which is why a plain button in a form can reload the page. Write type="button" for any button that runs JavaScript instead.
What is the difference between button and input type=submit?
Both submit a form. <button> can contain HTML (an icon, bold text) between its tags, while <input type="submit"> takes its label from the value attribute and can hold only plain text. Most modern code uses <button>.
How do I disable a button in HTML?
Add the disabled attribute: <button disabled>Save</button>. A disabled button cannot be clicked or focused and its name and value are not sent with the form. Remove the attribute (btn.disabled = false in JavaScript) to enable it again.
How do I make an HTML button go to another page?
Use a link styled as a button: <a href="/pricing" class="btn">See pricing</a>. A <button> is for actions on the current page. Wrapping a button in <a> is invalid HTML.
Why does my button reload the page?
It is inside a <form> and has no type, so it is a submit button and the browser sends the form and loads the response. Add type="button" to it, or call event.preventDefault() in a submit listener if you handle the form with JavaScript.