Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
HTML has no built-in cancel button type. Choose the control by what Cancel should do: use <button type="button"> for a custom in-page action, an <a> link to leave for a known URL, and formmethod="dialog" to close a native dialog. Use reset behavior only when you specifically want to restore a form’s default values.
Start with the intended behavior
| What Cancel should do | Use |
|---|---|
| Submit the form | <button type="submit"> |
| Navigate to a known page | <a href="/destination"> |
| Run code or change in-page state | <button type="button"> |
| Restore controls to their HTML default values | <button type="reset"> |
| Close a native dialog form without sending it to a server | formmethod="dialog" |
Cancel and reset are not synonyms. A cancel action might leave the page, close a panel, or discard edits; HTML does not choose that behavior for you.
The safest custom Cancel button
<form id="profile-form" action="/profile" method="post">
<!-- fields -->
<button type="submit">Save changes</button>
<button type="button" id="cancel-button">Cancel</button>
</form>
Specify the type on every button in a form. A button associated with a form whose type is missing or invalid normally acts as a submit button, so <button>Cancel</button> can submit the form. The HTML Standard defines submit, reset, and button behaviors; button has no built-in action. See the HTML Standard.
Recommended Free Tools
A type="button" control does nothing until you give it an action. It also does not initiate normal form submission or its constraint-validation process.
#1 Best Overall
When Cancel means “go back to this page”
If the destination is a known URL, use a link. It navigates without JavaScript and does not submit the form:
<form action="/profile/edit" method="post">
<!-- fields -->
<button type="submit">Save</button>
<a href="/profile">Cancel</a>
</form>
Style the link to look like a button if needed, but keep its link semantics: links navigate; buttons perform actions. Native links and buttons provide expected keyboard interaction and expose their roles to assistive technology. See W3C’s guidance on using HTML form controls and links.
If Cancel needs to check for unsaved changes or run other code before navigating, use a button instead:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
<button type="button" id="cancel-button">Cancel</button>
<script>
document.querySelector("#cancel-button").addEventListener("click", () => {
window.location.assign("/profile");
});
</script>
Use a destination that matches the product’s intended path. history.back() can send a user to an unrelated page—or be unhelpful if the form was opened directly or in a new tab. Prefer a known URL when that is where the user should go.
When Cancel means “discard my edits, but stay here”
For a static form, call reset() deliberately from a non-submit button:
<form id="settings-form">
<label>Display name
<input name="displayName" value="Taylor">
</label>
<button type="submit">Save</button>
<button type="button" id="discard-button">Cancel</button>
</form>
<script>
const form = document.querySelector("#settings-form");
document.querySelector("#discard-button").addEventListener("click", () => {
form.reset();
});
</script>
HTMLFormElement.reset() restores form controls to their default values, as described by MDN. Those defaults are not necessarily the latest values your app fetched. For example, assigning input.value = profile.name changes the current value, but does not necessarily change the default value used by reset.
For API-loaded edit forms, capture the loaded record as the baseline and restore it explicitly. A simple example for one field:
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Repair Windows errors before they cause bigger problems3Scan for outdated or missing drivers - takes under a minuteconst nameInput = document.querySelector("#name");
let originalName = "";
const profile = await fetch("/api/profile").then(response => response.json());
nameInput.value = profile.name;
originalName = profile.name;
document.querySelector("#cancel").addEventListener("click", () => {
nameInput.value = originalName;
});
For a larger form, keep a structured snapshot of all relevant values and restore it through your app’s state-management approach. Account for checkboxes, radio groups, multi-selects, file inputs, and custom widgets; a single text-value assignment is not a general-purpose restore operation.
Why type="reset" is usually not the right Cancel
A reset button immediately restores controls to their initial/default values. It does not navigate, close a modal, restore data fetched later, or ask before clearing fields. MDN advises generally avoiding reset buttons because they can be activated accidentally and erase entered data; see its button reference and form tutorial.
Rank #4
If the real intention is to clear fields, label the control accordingly—for example, Clear all fields—rather than labeling a destructive reset as Cancel.
Cancel in a native <dialog>
For a form inside a native dialog, use the dialog form method for the control that closes it:
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →<dialog id="edit-dialog">
<form method="dialog" id="dialog-form">
<label>Project name
<input name="projectName" required>
</label>
<button value="cancel" formmethod="dialog">Cancel</button>
<button value="save">Save</button>
</form>
</dialog>
<script>
const dialog = document.querySelector("#edit-dialog");
dialog.addEventListener("close", () => {
if (dialog.returnValue === "save") {
// Read or process the form values here.
}
});
</script>
formmethod="dialog" closes the dialog without sending form data to a server. The activating button’s value is available as the dialog’s returnValue. See MDN’s dialog reference. Test with required fields left empty: Cancel should still close the dialog, while Save should remain subject to the intended validation. Don’t use a validation-bypass attribute as a substitute for choosing the dialog behavior.
Decide whether to confirm unsaved changes
Do not interrupt users with a confirmation when nothing has changed. For meaningful edits that would be hard to recover—especially long, complex, or high-value forms—warn before discarding, retain a draft, or offer another recovery path. W3C guidance discusses confirmation before irreversible actions and ways to return without unwanted data loss.
A basic dirty-state example:
let dirty = false;
form.addEventListener("input", () => {
dirty = true;
});
cancelButton.addEventListener("click", () => {
if (!dirty || window.confirm("Discard your unsaved changes?")) {
window.location.assign("/dashboard");
}
});
Real applications should track changes accurately: a user may edit a field and then put it back exactly as it was. Framework forms often provide a dirty/pristine state for this purpose. Keep the prompt specific and offer a way to stay and continue editing.
Quick Recap
Accessibility and behavior checklist
- Use a native
<button>for an in-page action and a native<a>for navigation; don’t make a clickabledivorspan. - Give every form button an explicit type.
- Use a visible label that matches the consequence, such as “Cancel,” “Discard changes,” or “Clear all fields.” Don’t rely on an icon alone.
- Make sure keyboard users can reach and activate the control, and that closing a dialog or panel leaves focus in a sensible place.
- Warn or provide recovery when cancellation could destroy substantial work. W3C’s guidance covers review, correction, and undo patterns for consequential form actions: form undo.
Common problems
- Cancel submits the form: add
type="button"for a custom action, or use a link for navigation. A missing type normally means submit for a form-associated button. - Cancel only clears or reverts fields: that is reset behavior, not navigation. Use a link or explicit navigation code if the user should leave.
- Reset restores the wrong values: the form’s HTML defaults may differ from data loaded later. Save and restore an explicit baseline for the loaded record.
- Required-field errors prevent cancellation: use
type="button"for custom cancellation orformmethod="dialog"for a native dialog, not a normal form submission. - Back navigation goes somewhere unexpected: navigate to a known destination rather than blindly calling
history.back(). - A custom modal does not close: wire the button to the component’s close action; a plain
type="button"has no automatic cancel behavior. - You need to cancel an already-submitted order or transaction: a form control cannot undo a server-side action. That requires a separate service-supported process and clear instructions about its availability and timing. See W3C guidance on post-submission cancellation procedures.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

