Question
In the following HTML page, Firefox submits the form when the Remove Last Item button is clicked, while the Add Item button does not appear to behave the same way.
How can I prevent the Remove Last Item button from submitting the form?
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<html>
<body>
<form autocomplete="off" method="post" action="">
<p>Title:<input type="text" /></p>
<button onclick="addItem(); return false;">Add Item</button>
<button onclick="removeItem(); return false;">Remove Last Item</button>
<table>
<th>Name</th>
<tr>
<td><input type="text" id="input1" name="input1" /></td>
<td><input type="hidden" id="input2" name="input2" /></td>
</tr>
</table>
<input id="submit" type="submit" name="submit" value="Submit" />
</form>
</body>
</html>
function addItem() {
var v = $('form :hidden:last').attr('name');
var n = /(.*)input/.exec(v);
var newPrefix;
if (n[1].length == 0) {
newPrefix = '1';
} else {
newPrefix = parseInt(n[1]) + 1;
}
var oldElem = $('form tr:last');
var newElem = oldElem.clone(true);
var lastHidden = $('form :hidden:last');
lastHidden.val(newPrefix);
var pat = '=\"' + n[1] + 'input';
newElem.html(newElem.html().replace(new RegExp(pat, 'g'), '=\"' + newPrefix + 'input'));
newElem.appendTo('table');
$('form :hidden:last').val('');
}
function removeItem() {
var rows = $('form tr');
if (rows.length > 2) {
rows[rows.length - 1].html('');
$('form :hidden:last').val('');
} else {
alert('Cannot remove any more rows');
}
}
Short Answer
By the end of this page, you will understand why some buttons inside a form submit the form automatically, how the browser decides button behavior, and how to stop that submission safely using type="button", event handling, or form submit prevention in JavaScript.
Concept
In HTML, a <button> placed inside a <form> is treated as a submit button by default unless you explicitly say otherwise.
That means this button:
<button>Remove Last Item</button>
is effectively treated like this:
<button type="submit">Remove Last Item</button>
When clicked, the browser tries to submit the form.
This matters because many forms contain buttons that are not meant to submit anything. For example:
- add a row
- remove a row
- preview data
- open a dialog
- validate fields first
If you do not explicitly set the button type, the browser may submit the form when the button is clicked. Different browsers may appear to behave slightly differently depending on inline handlers, DOM changes, or timing, but the core rule is the same: inside a form, <button> defaults to submit.
The most reliable fix is to use:
<button type="button">Remove Last Item</button>
This tells the browser: “this is a normal clickable button, not a submit button.”
So for the original problem, both non-submit buttons should be written like this:
<button type="button" onclick="addItem()">Add Item</button>
<button type="button" onclick="removeItem()">Remove Last Item</button>
This is clearer and more robust than depending only on return false; in inline JavaScript.
Mental Model
Think of a form like a paper form on a clipboard.
- A submit button is the button that sends the form to the office.
- A normal button is just a tool on the desk, like “Add another page” or “Remove last line.”
If you place a button inside the form and do not label it, the browser assumes it is the send-to-the-office button.
So if you want a button that just performs an action on the page, you must label it as:
type="button"
Otherwise, the browser may try to send the form away.
Syntax and Examples
The main syntax is simple.
1. Default behavior inside a form
<form>
<button>Click me</button>
</form>
This button acts like a submit button.
2. Prevent form submission with type="button"
<form>
<button type="button">Click me</button>
</form>
This button does not submit the form.
3. Submit button when you actually want submission
<form>
<button type="submit">Submit</button>
</form>
Use this only for the real form submission action.
4. Better version of the original example
<form autocomplete="off" method="post" action="">
<p>Title: <input type="text" /></p>
<button type="button" onclick="addItem()">Add Item</button>
<button type="button" onclick="removeItem()">Remove Last Item</button>
<table>
<tr>
<th>Name</th>
</tr>
<tr>
<td><input type="text" id="input1" name="input1" /></td>
<td><input type="hidden" id="input2" name="input2" /></td>
</tr>
</table>
<input id="submit" type="submit" name="submit" value="Submit" />
</form>
Why this works
Add Itemis now just a normal button.Remove Last Itemis now just a normal button.- Only the final submit control sends the form.
5. Event-based prevention
Another common approach is preventing the default action in JavaScript:
<button id="removeBtn" type="submit">Remove Last Item</button>
document.getElementById('removeBtn').addEventListener('click', function (event) {
event.preventDefault();
removeItem();
});
This works too, but if the button is not supposed to submit at all, type="button" is usually the cleaner solution.
Step by Step Execution
Consider this small example:
<form>
<button id="remove">Remove</button>
</form>
What happens when you click it?
- The browser sees a
<button>inside a<form>. - Because no
typeis given, it treats the button astype="submit". - When the user clicks it, the browser starts the form submission process.
- If no code prevents that default behavior, the page submits or reloads.
Now look at this version:
<form>
<button id="remove" type="button">Remove</button>
</form>
What happens now?
- The browser sees a button inside a form.
- This time, the button is explicitly marked as
type="button". - When clicked, it behaves like a regular UI button.
- No form submission occurs.
Trace with JavaScript
<form>
<button type="button" onclick="sayHello()">Say Hello</button>
<button type="submit">Submit</button>
</form>
<script>
function sayHello() {
alert('Hello');
}
</script>
Step by step:
-
Click Say Hello
sayHello()runs- alert appears
- form does not submit
-
Click Submit
- browser submits the form
That separation is exactly what you want in real forms.
Real World Use Cases
Buttons that should not submit forms are very common in real applications.
Dynamic form builders
Examples:
- add another email field
- remove a phone number field
- add a new address row
These buttons change the form structure, but should not send data yet.
Shopping carts
Examples:
- increase quantity
- decrease quantity
- remove item
These actions often update the page or send AJAX requests, not a full form submission.
Admin dashboards
Examples:
- preview settings
- test API connection
- generate slug from title
These are helper actions inside forms.
Multi-step forms
Examples:
- validate current step
- show more options
- go back to previous step
Only the final action should submit the full form.
Data entry tools
Examples:
- duplicate row
- clear section
- autofill values
These are interface actions, not submit actions.
Real Codebase Usage
In real projects, developers usually combine correct HTML semantics with JavaScript event handling.
Common pattern: explicit button types
<button type="button" id="addBtn">Add</button>
<button type="button" id="removeBtn">Remove</button>
<button type="submit">Save</button>
This makes intent obvious.
Common pattern: attach events in JavaScript
document.getElementById('addBtn').addEventListener('click', addItem);
document.getElementById('removeBtn').addEventListener('click', removeItem);
This is cleaner than inline onclick because:
- HTML stays simpler
- JavaScript is easier to test
- behavior is easier to maintain
Guard clauses
Your removeItem() already uses a guard-like pattern:
if (rows.length <= 2) {
alert('Cannot remove any more rows');
return;
}
This is common in real code because it stops invalid actions early.
Validation before submit
Developers often allow only one real submit path:
form.addEventListener('submit', function (event) {
if (!isValid()) {
event.preventDefault();
}
});
All helper buttons remain type="button", while actual submission goes through validation.
Progressive enhancement
Good codebases ensure the form still behaves correctly even if JavaScript changes. Explicit button types reduce accidental submissions and make browser behavior more predictable.
Common Mistakes
1. Forgetting that <button> defaults to submit
Broken example:
<form>
<button onclick="removeItem()">Remove</button>
</form>
Problem:
- The browser treats it as a submit button.
removeItem()may run, but the form may submit afterward.
Fix:
<button type="button" onclick="removeItem()">Remove</button>
2. Relying only on return false in inline handlers
Example:
<button onclick="removeItem(); return false;">Remove</button>
This often works, but it mixes behavior into HTML and can be fragile in larger codebases. It is better to define correct button types first.
Better:
<button type="button" onclick="removeItem()">Remove</button>
3. Using type="submit" by accident
Broken example:
<button type="submit" onclick="addItem()">Add</button>
If the button is only for UI interaction, submit is the wrong type.
4. Preventing submit in JavaScript when simple HTML would solve it
Overcomplicated version:
document.getElementById('btn').addEventListener('click', function (e) {
e.preventDefault();
removeItem();
});
This works, but if the button should never submit, simply use:
<button type="button">Remove</button>
5. Confusing <input type="button"> and <button>
These are similar but not identical.
<input type="button" value="Remove" />
<button type="button">Remove</button>
Both can be non-submit buttons, but <button> is usually more flexible because it can contain richer content.
6. Not separating submit actions from UI actions
A form should usually have:
- helper buttons with
type="button" - one intentional submit control with
type="submit"
Comparisons
| Option | Submits form? | Best use case | Notes |
|---|---|---|---|
<button> | Yes, by default inside a form | Rarely safe without explicit type | Browser treats it as submit |
<button type="submit"> | Yes | Real form submission | Use for Save, Send, Submit |
<button type="button"> | No | UI actions inside a form | Best for add/remove/preview |
<input type="submit"> | Yes | Simple form submission | Older but still valid |
<input type="button"> | No | Simple clickable button | Less flexible than <button> |
event.preventDefault() | Prevents submission if used in event handler | When you need submit-like markup but custom behavior | Useful, but not a replacement for correct button type |
type="button" vs return false
| Approach | Where it works | Recommended? | Why |
|---|---|---|---|
type="button" | HTML | Yes | Clear, semantic, browser-safe |
return false in inline onclick | Inline handlers | Sometimes | Works, but mixes HTML and JS |
event.preventDefault() | JavaScript event listeners | Yes | Good when handling events programmatically |
Best rule
If a button is not supposed to submit the form, make it:
<button type="button">...</button>
Cheat Sheet
Quick rule
Inside a <form>, a <button> defaults to:
<button type="submit">
To stop submission
Use:
<button type="button">Remove</button>
Button types
<button type="submit">Submit form</button>
<button type="button">Run JavaScript only</button>
<button type="reset">Reset form fields</button>
Safe pattern
<form>
<button type="button" onclick="addItem()">Add Item</button>
<button type="button" onclick="removeItem()">Remove Item</button>
<button type="submit">Submit</button>
</form>
JavaScript prevention
button.addEventListener('click', function (event) {
event.preventDefault();
});
Best practice
- Use
type="button"for helper actions - Use
type="submit"only for real submission - Prefer event listeners over inline
onclickin production code - Keep one clear submit path
Edge case to remember
If you omit type, browser behavior follows the default submit behavior for buttons inside forms.
FAQ
Why does a button submit a form even if I did not set type="submit"?
Because <button> inside a form defaults to type="submit" unless you explicitly set another type.
What is the easiest way to stop a button from submitting a form?
Set the button type to:
type="button"
Is return false enough to stop form submission?
It can work in inline handlers, but it is better to use type="button" for non-submit buttons and event.preventDefault() in JavaScript when needed.
Should I use <button> or <input type="button">?
Usually <button> is preferred because it is more flexible and easier to style, but both can be used for non-submit actions.
When should I use event.preventDefault()?
Use it when you are handling events in JavaScript and want to stop the browser's default behavior, such as form submission or link navigation.
Why did one browser seem to submit but another behaved differently?
Browser differences can appear due to event timing, DOM updates, and older implementations. Setting explicit button types removes this ambiguity.
Can I have multiple buttons inside one form?
Yes. Just make sure only actual submit actions use type="submit". Helper actions should use type="button".
Mini Project
Description
Build a small dynamic form where users can add or remove item rows without accidentally submitting the form. This project demonstrates the difference between helper buttons and actual submit buttons inside a form.
Goal
Create a form with Add and Remove buttons that modify the form safely, while only the Submit button sends the form.
Requirements
- Create a form with one text input for a title.
- Add an
Add Itembutton that appends a new row to a list. - Add a
Remove Last Itembutton that removes the last added row. - Ensure neither helper button submits the form.
- Keep one real submit button for sending the form.
Keep learning
Related questions
Allow Only Numeric Input (0-9) in HTML Input Using jQuery
Learn how to allow only digits 0-9 in an HTML input using jQuery, with examples, validation tips, common mistakes, and best practices.
Apply CSS !important with jQuery .css()
Learn why jQuery .css() cannot set !important and how to use CSSStyleDeclaration.setProperty() to apply inline important styles safely.
CSS ::before and ::after on Input Elements
Learn why CSS ::before and ::after usually do not work on input elements, what replaced elements are, and practical alternatives.