Web Development
Form Handling
JavaScript
User Interface
HTML Tips

How to prevent buttons from submitting forms

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

A <button> element inside a <form> submits the form by default. This catches developers off guard because the HTML spec sets the default type attribute of a button to submit, not button. Every approach for preventing this behavior boils down to one idea: tell the browser that a particular button is not a submit trigger. The three main techniques are setting type="button", calling event.preventDefault() in JavaScript, and using the formaction attribute to redirect submission. Each fits different scenarios depending on how much control you need.

Why Buttons Submit Forms by Default

The HTML specification defines three valid values for a button's type attribute:

  • submit sends the form data to the server. This is the default when type is omitted.
  • button does nothing on its own. It exists purely as a JavaScript hook.
  • reset clears all form fields back to their initial values.

Because submit is the implicit default, any <button> placed inside a <form> without an explicit type attribute acts as a submit trigger. This is the root cause of most unintended form submissions.

html
1<!-- This button WILL submit the form -->
2<form action="/submit">
3  <button>Save Draft</button>
4</form>
5
6<!-- This button will NOT submit the form -->
7<form action="/submit">
8  <button type="button">Save Draft</button>
9</form>

Method 1: Set type="button"

The simplest and most reliable solution is to explicitly set type="button" on any button that should not trigger form submission. This requires zero JavaScript and works in every browser.

html
1<form id="settings-form" action="/settings">
2  <input type="text" name="username" />
3
4  <button type="button" onclick="addAnotherField()">Add Field</button>
5  <button type="button" onclick="showPreview()">Preview</button>
6  <button type="submit">Save Settings</button>
7</form>

This is the recommended approach for the majority of cases. It is declarative, easy to audit, and has no runtime cost.

Method 2: event.preventDefault() in JavaScript

When you need conditional logic, such as running validation before deciding whether to submit, event.preventDefault() gives you programmatic control. This method works on both button clicks and the form's own submit event.

Preventing on button click

javascript
1const previewBtn = document.getElementById("previewBtn");
2
3previewBtn.addEventListener("click", function (event) {
4  event.preventDefault();
5  renderPreview();
6});

Preventing on form submit

Intercepting the form's submit event is more robust because it catches submissions triggered by the Enter key, not just button clicks.

javascript
1const form = document.getElementById("checkout-form");
2
3form.addEventListener("submit", function (event) {
4  event.preventDefault();
5
6  if (!validateFields()) {
7    showErrors();
8    return;
9  }
10
11  // Manual submission after validation passes
12  fetch("/api/checkout", {
13    method: "POST",
14    body: new FormData(form),
15  });
16});

React equivalent

In React, the pattern is identical but uses synthetic events:

jsx
1function CheckoutForm() {
2  const handleSubmit = (e) => {
3    e.preventDefault();
4    // custom submission logic
5  };
6
7  return (
8    <form onSubmit={handleSubmit}>
9      <input name="email" type="email" />
10      <button type="submit">Pay</button>
11      <button type="button" onClick={resetCart}>Clear Cart</button>
12    </form>
13  );
14}

Method 3: The formaction Attribute

HTML5 introduced formaction, which lets a button override the form's action URL. While not a prevention technique per se, it solves the related problem of having multiple submit buttons that send data to different endpoints.

html
1<form action="/save-draft" method="post">
2  <textarea name="content"></textarea>
3
4  <button type="submit">Save Draft</button>
5  <button type="submit" formaction="/publish">Publish</button>
6</form>

This avoids the need for JavaScript to reroute submissions and keeps the form semantic.

Comparison of Methods

MethodRequires JavaScriptConditional LogicBrowser SupportBest For
type="button"NoNoAll browsersStatic non-submit buttons
event.preventDefault()YesYesAll browsersValidation, async submission
return false (inline)Inline JSLimitedAll browsersLegacy codebases only
formactionNoNoHTML5+Multiple submit endpoints

Full Working Example

Here is a complete example combining multiple techniques in a single form. The "Add Item" button dynamically inserts rows without submitting. The "Submit Order" button runs client-side validation first.

html
1<form id="orderForm" action="/api/orders" method="post">
2  <div id="items">
3    <input type="text" name="item[]" placeholder="Item name" />
4  </div>
5
6  <button type="button" id="addItem">Add Item</button>
7  <button type="submit">Submit Order</button>
8</form>
9
10<script>
11  document.getElementById("addItem").addEventListener("click", function () {
12    const input = document.createElement("input");
13    input.type = "text";
14    input.name = "item[]";
15    input.placeholder = "Item name";
16    document.getElementById("items").appendChild(input);
17  });
18
19  document.getElementById("orderForm").addEventListener("submit", function (e) {
20    const inputs = document.querySelectorAll('input[name="item[]"]');
21    for (const input of inputs) {
22      if (!input.value.trim()) {
23        e.preventDefault();
24        input.focus();
25        alert("All item fields must be filled.");
26        return;
27      }
28    }
29  });
30</script>

Common Pitfalls

Forgetting that the default type is submit. This is the number one cause of unexpected form submissions. Every <button> inside a form should have an explicit type attribute, even if it is type="submit". Being explicit prevents ambiguity.

Using return false in modern code. The inline return false technique only works when the handler is assigned via an onclick attribute. It does not work with addEventListener. Mixing these styles in a codebase leads to inconsistent behavior.

Calling preventDefault on the wrong event. Preventing the button's click event stops that specific button from submitting, but the user can still submit the form by pressing Enter in a text input. If you need to block all submission paths, listen on the form's submit event instead.

Nesting forms. HTML does not allow nested <form> elements. If you accidentally nest forms, browser behavior becomes unpredictable and buttons may submit the wrong form or no form at all.

Disabling buttons instead of changing their type. Setting disabled on a button does prevent submission, but it also prevents all interaction and changes the visual appearance. Use type="button" when you still want the button to be clickable.

Summary

The default type of a <button> in HTML is submit, which causes unintended form submissions when buttons are placed inside forms without an explicit type. The most reliable fix is setting type="button" on every button that should not submit. For dynamic validation or conditional submission, use event.preventDefault() on the form's submit event. Always prefer explicit type attributes over JavaScript workarounds, and audit your forms to ensure every button has a clearly defined role.


Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.