splitforms.com
← Back to the journal

Prevent the Enter Key From Submitting a Form (HTML, JS, React)

Stop Enter submitting a form: how implicit submission works, a keydown fix that keeps textarea newlines, and React/Vue versions that stay accessible.

Start free — 500 submissionsSee pricing →No card, no time limit. Pro is $5 per month.
Short answer
Pressing Enter in a single-line <input> can submit the whole form under HTML's implicit submission rules. Use type="button" on non-submit buttons, then add one keydown listener on the form that blocks Enter only on text-like inputs—not on textarea or IME composition. React and Vue can mirror the same checks on the form element.
Try it on your own form

Point any HTML form at one endpoint. 500 free submissions — no card, no time limit — and unlimited forms.

Create free account

Why Enter submits your form

Browsers follow the HTML spec's implicit submission rule. When the user presses Enter in a single-line text field inside a <form>, the browser submits that form if any of these are true:

  • The form has a submit control (a <button type="submit">, an <input type="submit">, or a <button> with no type attribute—the default is submit).
  • Or the form has exactly one single-line text field and no submit button (Enter still submits).

Enter inside a <textarea> never submits; it inserts a new line. That distinction matters when you add JavaScript to block Enter: you must not break textarea editing.

Accidental submits often show up alongside duplicate POSTs; see prevent duplicate form submissions. Multi-step flows are a common trigger—multi-step form HTML, CSS and JavaScript covers patterns where Enter on step one should not fire the whole submit.

Fix 1: HTML only — use type="button"

Any <button> inside a form without an explicit type behaves as type="submit". Buttons that should only run JavaScript (add row, open modal, calculate) need type="button" so a stray Enter or click does not submit the form.

<form action="/save" method="POST">
  <input name="sku" />
  <button type="button" id="scan">Scan barcode</button>
  <button type="submit">Save</button>
</form>

This fixes mistaken submits from extra buttons, but it does not stop Enter in a text field when a real submit button is still present. For that you need JavaScript.

Fix 2: keydown on the form (recommended)

Attach one keydown listener to the form. Call e.preventDefault() when the key is Enter, the event target is an INPUT, and the input's type is not submit, button, checkbox, or radio. Do not run this for TEXTAREA. Skip events where e.isComposing is true so Chinese, Japanese, and Korean IME users can confirm composed text with Enter.

const form = document.querySelector("form");

form.addEventListener("keydown", (e) => {
  if (e.key !== "Enter" || e.isComposing) return;

  const el = e.target;
  if (!(el instanceof HTMLInputElement)) return;

  const skipTypes = new Set(["submit", "button", "checkbox", "radio"]);
  if (skipTypes.has(el.type)) return;

  e.preventDefault();
});

The submit button still works: clicking it (or focusing it and activating it) runs a normal submit. Only Enter inside single-line inputs is blocked. For the difference between programmatic submit() and user-driven submission, see form.submit() vs requestSubmit().

Fix 3: Enter moves to the next field

Some data-entry UIs want Enter to behave like Tab. After preventDefault(), focus the next control in form.elements:

form.addEventListener("keydown", (e) => {
  if (e.key !== "Enter" || e.isComposing) return;
  const el = e.target;
  if (!(el instanceof HTMLInputElement)) return;
  if (["submit", "button", "checkbox", "radio"].includes(el.type)) return;

  e.preventDefault();
  const fields = [...form.elements].filter(
    (node) =>
      node instanceof HTMLInputElement ||
      node instanceof HTMLSelectElement ||
      node instanceof HTMLTextAreaElement
  );
  const i = fields.indexOf(el);
  if (i >= 0 && i < fields.length - 1) fields[i + 1].focus();
});

Keep a visible submit control on the last step so users who expect Enter to submit on a simple form are not surprised on the final field.

React and Vue

React: put the same logic on the form's onKeyDown:

function BlockEnterSubmit({ children }: { children: React.ReactNode }) {
  return (
    <form
      onKeyDown={(e) => {
        if (e.key !== "Enter" || e.nativeEvent.isComposing) return;
        const t = e.target;
        if (!(t instanceof HTMLInputElement)) return;
        if (["submit", "button", "checkbox", "radio"].includes(t.type)) return;
        e.preventDefault();
      }}
    >
      {children}
    </form>
  );
}

Vue 3: you can use @keydown.enter on a specific input with .prevent, but that blocks Enter only on that field. For the whole form, use @keydown on <form> with the same target checks as above. Per-input: @keydown.enter.prevent on a search box is fine when the form has a separate Search button.

Why not onsubmit return false?

Returning false from onsubmit or calling preventDefault() on every submit event stops all submissions—including when the user clicks the submit button or presses Enter on purpose. The keydown approach is narrower: it targets accidental Enter in text fields only.

Accessibility: keyboard users often rely on Enter to submit a short contact or login form. Only disable implicit Enter where accidental submits cause real harm (partial multi-step data, warehouse scanners, inline grids). Always leave a clear submit action and test with the keyboard alone.

Ship a form that actually posts

Blocking Enter does not replace a working endpoint. Point your action at a handler that accepts POST, or send FormData with fetch after preventDefault() on submit. Get a free splitforms access key and POST to https://splitforms.com/api/submit. For button types and defaults, see the <button> reference.

FAQ

Why does pressing Enter submit my form?

HTML implicit submission: when you press Enter in a single-line text field, the browser submits the form if it has a submit button, or if the form has only one single-line field. That is by design so keyboard users can submit without tabbing to the button.

How do I stop Enter submitting but keep new lines in a textarea?

Enter in a textarea never triggers implicit submission; it inserts a newline. If you add a keydown listener on the form, skip TEXTAREA (and skip INPUT types like submit and checkbox). Only call preventDefault on Enter for single-line inputs where accidental submit is the problem.

Is disabling Enter bad for accessibility?

Often yes. Many users expect Enter to submit a simple form. Block Enter only where accidental submits are common (multi-step wizards, barcode scanners, dense data entry). Keep a visible submit button and do not block Enter on the final step unless you have a clear alternative.

How do I stop Enter submitting in React?

Put the same keydown logic on the form’s onKeyDown handler: if key is Enter, target is an INPUT (not submit/button/checkbox/radio), and not isComposing, call preventDefault. Do not use onSubmit return false—that blocks intentional button submits too.

Spec: HTML implicit submission.

Related articles

More practical guidance from tutorials.

Browse the journal →
Tutorials

How to Remove the Arrows From a Number Input (CSS, Tailwind, React)

Hide the number input spin buttons with ::-webkit-inner-spin-button and appearance: textfiel…

7 min readRead →
Tutorials

How to Change the Autofill Background Color of an Input (CSS, Tailwind)

Remove Chrome's yellow autofill background with input:-webkit-autofill, inset box-shadow, -w…

7 min readRead →
Tutorials

input type=number maxlength Not Working? 4 Fixes That Work

Why maxlength is ignored on input type=number, plus four fixes: min/max, oninput slice, text…

8 min readRead →

Explore this topic

Start with the overview, then move into focused guides.

OverviewWhat Is a Form Backend? (Complete Guide)Start here →GuideSelf-Hosted vs SaaS Form BackendRead →GuideForm Backend vs Form BuilderRead →GuideWhere Do Form Submissions Go?Read →ReferenceForm backend guideOpen →

Building forms with ChatGPT, Claude, Cursor, or v0? Connect the native MCP server and give your agent a production form backend.

Explore the MCP server →

Give your form a production backend.

One endpoint adds delivery, spam filtering, storage, and integrations. Start with 500 free submissions — no card, no time limit.

Create free accountRead the docs →
Secure checkoutSSL encryptionPrivacyProtected
VISAAMERICANEXPRESSstripe