splitforms.com

HTML · FORM ATTRIBUTE

HTML required attribute: make form fields mandatory (live demo)

Last reviewed

The required attribute makes a form control mandatory: the browser blocks submission and shows a message until the control has a value. It is a usability check, not security, because anyone can POST without it.

  • 500 free total
  • No backend
  • Copy-paste ready
Live demo · runs in your browser, nothing is sent
<form>
Reply by radio
Terms checkbox

Press Submit with the form empty. The browser stops it, and this panel lists each control that blocked it with validity.valueMissing and the browser's own validationMessage. The readonly and hidden fields are required too, yet never block.

Copy-paste code

HTML Required Attribute code you can paste today.

Replace YOUR_ACCESS_KEY with a key from your free splitforms dashboard. The form posts to one endpoint — submissions land in your inbox and dashboard with spam filtering built in.

Get free access key
required.html
<form action="https://splitforms.com/api/submit" method="POST">
  <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY">

  <label for="name">Name</label>
  <input type="text" id="name" name="name" autocomplete="name" required>

  <label for="email">Email</label>
  <input type="email" id="email" name="email" autocomplete="email" required>

  <!-- The empty first option counts as "nothing picked yet" -->
  <label for="topic">Topic</label>
  <select id="topic" name="topic" required>
    <option value="">Choose a topic…</option>
    <option value="sales">Sales</option>
    <option value="support">Support</option>
  </select>

  <!-- required on one radio makes the whole group required -->
  <fieldset>
    <legend>Reply by</legend>
    <label><input type="radio" name="reply_by" value="email" required> Email</label>
    <label><input type="radio" name="reply_by" value="phone" required> Phone</label>
  </fieldset>

  <label for="message">Message</label>
  <textarea id="message" name="message" rows="4" required></textarea>

  <label><input type="checkbox" name="consent" value="yes" required> You may contact me about this request</label>

  <!-- Honeypot: hidden from people, bots fill it in -->
  <input type="checkbox" name="botcheck" style="display:none" tabindex="-1" autocomplete="off">

  <button type="submit">Send</button>
</form>

Key facts

What does the required attribute do?

required is a boolean attribute for <input>, <select> and <textarea>. While a required control has no value, the browser cancels a normal submit, usually focuses the control and shows its validation message. The check runs only in the browser, so a request sent straight to your endpoint skips it.

What does the required attribute do?
FactDetail
Attribute typeBoolean: its presence turns it on. required, required="" and required="required" all mean the same, and required="false" is still required.
Works on<input> (text-like, date and time, number, checkbox, radio and file types), <select> and <textarea>.
Ignored ontype="hidden", range, color and button types, on a readonly text, number or date field or <textarea>, and on any disabled control.
When it runsOn every normal submit: a submit button, Enter in a text field, or form.requestSubmit(). novalidate, formnovalidate and form.submit() skip it.
JavaScriptel.validity.valueMissing is true while a required control is empty. form.checkValidity() runs the checks; form.reportValidity() also shows the message.
CSS:required and :optional follow the attribute. :invalid matches an empty required field as soon as the page loads; :user-invalid waits until the person edits it or tries to submit.
Screen readersNative required is announced to assistive technology, so aria-required is mainly for custom controls that are not native form fields.
SecurityNone. Anyone can POST to the form's action URL without running it, so check required fields on the server.

Browser validation can be skipped; splitforms still filters spam and saves each accepted submission, so check required fields in your webhook handler before acting on a submission. Webhooks come with Pro ($5/month) or Annual ($49/year). Checked against the splitforms submit code on 2 October 2026.

Sources: WHATWG HTML Standard: the required attribute · WHATWG: boolean attributes · WHATWG: interactively validate the constraints · MDN: required · MDN: aria-required

Every control

When does required block the submit for each control?

A required control blocks the submit while it is suffering from being missing, which the HTML Standard defines per control. Controls that are barred from constraint validation ignore required. The last column is what the server receives when validation is skipped, for example with novalidate.

When does required block the submit for each control?
ControlWhat required meansSent if validation is skipped
text, search, tel, password, <textarea>The value must not be the empty string. A single space counts as a value.name= (an empty string)
email, urlLeading and trailing spaces are stripped first, so spaces alone still fail.email= (an empty string)
date, time, number and other typed inputsThe field needs a complete value. A half-typed date has an empty value and is blocked.name= (an empty string)
checkboxThe box must be checked.Nothing: the key is missing
radiorequired on any radio in a same-name group, even a disabled one, makes the whole group required: one radio must be picked.Nothing: the key is missing
<select>Fails while the selected option is the placeholder: the first option, when its value is "" and it is not inside an <optgroup>. Without one, the first option is selected by default and required always passes.topic= (the placeholder's empty value)
<select multiple>At least one option must be selected.Nothing: the key is missing
fileAt least one file must be chosen.With multipart/form-data, an empty file part with filename=""; otherwise name=
hidden, range, colorrequired does not apply. Hidden inputs are barred from validation; range and color always have a value.Their value
A readonly text, number or date field, or <textarea>Barred from constraint validation, so required is ignored even when the field is empty. readonly does not apply to checkboxes, radios, files or <select>, so it does not switch required off there.Its value, even an empty string
Any disabled controlBarred from constraint validation, so required is ignored.Nothing: disabled controls are never sent
Hidden with CSS or the hidden attributeStill validated. An empty one blocks the submit, but the browser has nowhere to show the message.Its value, like a visible field

The live demo above reads the same rules from your own browser: the readonly and hidden fields are required but never block. For the value each input type submits, see the input types table.

Sources: WHATWG: suffering from being missing · WHATWG: barred from constraint validation · WHATWG: checkbox state · WHATWG: radio button state · WHATWG: placeholder label option · WHATWG: file upload state · WHATWG: readonly · WHATWG: hidden state · MDN: required

Attributes · required

Which attributes and APIs work with required?

These switch the check off, change its message or read its result. MDN's constraint validation guide covers pattern, minlength and the other checks.

HTML Required Attribute attributes and what each one does
AttributeWhat it doesDocs
requiredBoolean. On <input>, <select> and <textarea>: the control needs a value before the form submits.MDN
novalidateOn the <form>. Turns off every browser check for that form, required included, so every submit goes through.MDN
formnovalidateOn one submit button. Skips validation for submits from that button only, such as a Save draft button.MDN
formOn a button or control outside the <form>: the form's id. It joins that form, so an outside submit button validates and submits it.MDN
readonlyBars a text-like input or textarea from validation, so required stops applying.MDN
disabledBars the control from validation and leaves it out of the submission.MDN
validity.valueMissingJavaScript: true while a required control has no value.MDN
setCustomValidity()JavaScript: replaces the browser's message. Any non-empty message keeps the field invalid until you clear it with "".MDN
reportValidity()JavaScript: runs the checks, shows the first message and returns false if anything fails.MDN

Common mistakes

What are the common required attribute mistakes?

Four details decide whether required runs at all. For a symptom-by-symptom checklist, see required attribute not working.

  1. novalidate turns every check off

    <form novalidate> skips validation for every submit, and formnovalidate on a submit button skips it for that button only. Keep both off the main submit path, or call form.reportValidity() yourself.

  2. A submit button outside the form does nothing

    A button only submits, and validates, the form it belongs to. If it sits outside the <form>, give it form="contact" with the form's id; otherwise it neither validates nor submits.

  3. required without a name still blocks the submit

    Validation covers every control in the form, named or not. An empty required field with no name stops the submit, and once filled it is still never sent. Give every field a name.

  4. Hiding a field does not switch required off

    display: none and the hidden attribute do not bar a control from validation. An empty required field you hid stops the submit with no visible message, and Chrome logs an "is not focusable" error in the console. Add disabled while it is hidden, or remove required.

Sources: WHATWG HTML Standard: the required attribute · WHATWG: barred from constraint validation · MDN: required · MDN: Constraint validation

setCustomValidity

How do I change the required error message?

Set your own text in the field's invalid event, which fires when a submit finds it empty, and clear it on every edit. The browser then shows your message instead of its default. Clearing matters: any non-empty custom message keeps the field invalid, so without the input handler the form could never submit.

The message only appears during a submit or reportValidity(). To show it as people type, render your own error text next to the field.

custom-message.html
<label for="email">Work email</label>
<input type="email" id="email" name="email" required>

<script>
  const email = document.getElementById("email");

  // Fires when a submit finds the field invalid
  email.addEventListener("invalid", () => {
    if (email.validity.valueMissing) {
      email.setCustomValidity("Enter your work email so we can reply.");
    }
  });

  // Clear it on every edit, or the field stays invalid for good
  email.addEventListener("input", () => email.setCustomValidity(""));
</script>

:user-invalid

Should I style :invalid or :user-invalid?

Use :user-invalid for error colors. :invalid matches every empty required field as soon as the page loads, so the whole form starts red. :user-invalid waits until the person has changed the field or tried to submit, then matches the same failures. MDN lists it as Baseline since November 2023.

required-styles.css
/* Not :invalid: it matches on page load, before anyone
   typed, so the whole form would start red. */

/* Matches after an edit or a submit attempt */
input:user-invalid,
select:user-invalid,
textarea:user-invalid {
  border-color: #c93d00;
  outline: 2px solid #c93d00;
  outline-offset: 1px;
}

input:user-valid,
select:user-valid,
textarea:user-valid {
  border-color: #1f7a4d;
}

:has(:required)

How do I add a required asterisk with CSS?

Wrap each label and control in a container and let :has(:required) add the asterisk, so it always matches the markup. MDN lists :has() as Baseline since December 2023. The asterisk is for sighted users only: screen readers already announce the field as required from the attribute. Say what it means once, above the form.

required-asterisk.html
<p>Fields marked * are required.</p>

<div class="field">
  <label for="name">Name</label>
  <input type="text" id="name" name="name" required>
</div>

<div class="field">
  <label for="company">Company</label>
  <input type="text" id="company" name="company">
</div>

<style>
  .field:has(:required) > label::after {
    content: " *";
    color: #c93d00;
  }
</style>

checkbox group

How do I require at least one checkbox in a group?

required on a checkbox means that box must be checked, so it can't say "any one of these". Set a custom message on the first box while none is checked instead. The browser then blocks the submit and shows it like any required field, and the message clears as soon as one box is ticked. The checkbox page has the full version.

require-one-checkbox.html
<fieldset id="topics">
  <legend>Topics (pick at least one)</legend>
  <label><input type="checkbox" name="topic" value="pricing"> Pricing</label>
  <label><input type="checkbox" name="topic" value="api"> API</label>
</fieldset>

<script>
  const boxes = [...document.querySelectorAll("#topics input")];
  const check = () =>
    boxes[0].setCustomValidity(
      boxes.some((b) => b.checked) ? "" : "Pick at least one topic.",
    );
  boxes.forEach((b) => b.addEventListener("change", check));
  check();
</script>

reportValidity()

How do I keep required checks when sending with fetch?

A submit listener is safe: the browser only fires submit after the checks pass, so preventDefault() plus fetch keeps required. The checks are skipped when you send from a type="button" click handler or after form.submit(). In those paths call form.reportValidity() first: it runs the same checks, shows the message and returns false if a field is missing.

form.requestSubmit() is the other option: it validates, then fires a normal submit event.

validate-before-fetch.html
<form id="contact" action="https://splitforms.com/api/submit" method="POST">
  <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY">
  <input type="email" name="email" required>
  <button type="button" id="send">Send</button>
</form>

<script>
  const form = document.getElementById("contact");

  document.getElementById("send").addEventListener("click", async () => {
    // A type="button" click is not a submit: nothing was checked yet
    if (!form.reportValidity()) return;

    const res = await fetch(form.action, { method: "POST", body: new FormData(form) });
    const data = await res.json();
    if (!res.ok) return alert(data.message);
    form.reset();
  });
</script>

Copy-paste ready

The HTML Required Attribute example below is a complete, working form — paste it into any HTML page and it submits, no edits to the markup required.

No backend to build

Your html required attribute form posts to one endpoint. No server, PHP, or API route — accepted submissions are saved to your dashboard before owner notification email is attempted; delivery time and inbox placement depend on provider and recipient settings.

A form that really submits

Unlike a static reference snippet, this required form actually sends data to a free splitforms backend, with spam filtering built in.

How it works

How to add HTML Required Attribute to any page.

Copy the html required attribute example, drop in your free access key, and paste it into any page — submissions start landing in your dashboard.

Copy the code

Copy the HTML Required Attribute example below.

Add your access key

Replace YOUR_ACCESS_KEY with a free splitforms key from the dashboard.

Paste into your site

Drop the form into any HTML page. Submissions arrive in your dashboard.

How SplitForms works

What happens after someone submits your form?

splitforms receives the submission, filters spam, saves it to your dashboard and emails you — then, on paid plans, sends it on to your webhooks and integrations. No backend infrastructure to build.

A SplitForms contact form submission launching straight to your inbox

Add your endpoint

Point your form to your unique SplitForms endpoint. That's it.

HTML form pointing at a SplitForms submit endpoint

Receive submissions

We instantly capture and organize every submission in your inbox.

Submissions inbox with searchable leads and status pills

Route anywhere

Send data to email, spreadsheets, CRMs, webhooks, and 7,000+ apps.

Generic integration tiles for email, sheets, chat, CRM, automate, and webhook

No credit card required. Set up in under 60 seconds.

Connect & automate

Where can submissions go besides email?

On paid plans, submissions can also go to Slack, Discord, Google Sheets, Notion, Airtable, Zapier or any signed webhook — and splitforms works on the platforms you build on, from WordPress and Shopify to Next.js. With Stripe connected, your forms can take payments too.

Connect your SplitForms form to Slack, Google Sheets, Mailchimp, Zapier and more
NewTake payments on your formsDeposits, bookings, order forms — submitters check out through Stripe and the money goes straight to your Stripe account. Included on every paid plan.See plans →

Setup guides for the stacks you use

Questions

HTML Required Attribute questions, answered.

View all FAQs
What does the required attribute do in HTML?

It makes a form control mandatory. While an <input>, <select> or <textarea> with required has no value, the browser blocks a normal submit, focuses the control and shows a message such as "Please fill out this field." It is a boolean attribute, so writing required on its own is enough.

How do I make a checkbox required in HTML?

Add required to the checkbox: <input type="checkbox" name="terms" value="yes" required>. The form will not submit until it is checked. required applies to each box on its own, so to require at least one box in a group, call setCustomValidity() on the first box while none is checked.

How do I make a select dropdown required?

Add required to the <select> and make its first option a placeholder with an empty value, such as <option value="">Choose…</option>. The browser treats that option as no choice and blocks the submit until a real option is picked. Without an empty first option, the first option is selected by default and required always passes.

How do I make a radio button group required?

Put required on a radio in the group; MDN recommends putting it on every radio in the group, or on none, to keep the markup easy to maintain. Radios with the same name form one group, so required on any of them means one radio in the group must be picked before the form submits.

Is required="false" the same as not required?

No. required is a boolean attribute, so its presence is what counts: required="false" still makes the field required. To make a field optional, remove the attribute, or set input.required = false in JavaScript.

Does required work on hidden, readonly or disabled fields?

No. Hidden inputs, readonly fields and disabled controls are barred from constraint validation, so required has no effect on them. A field hidden with CSS is different: it is still validated, and an empty one still blocks the submit.

Does a field with only spaces pass required?

In a text field or textarea, yes: a space is a value, so required passes. Email and URL inputs strip leading and trailing spaces first, so spaces alone fail there. To reject blank text in an input, add pattern=".*\S.*"; a textarea has no pattern attribute, so check it with JavaScript. Either way, trim the value on the server.

How do I change the "Please fill out this field" message?

Call setCustomValidity("Your message") on the control in its invalid event, and clear it with setCustomValidity("") in its input event. Any non-empty custom message keeps the field invalid, so if you never clear it the form can't submit.

Is the required attribute enough to validate a form?

No. It only runs in the browser, and anyone can POST to your endpoint without it. Browser validation can be skipped; splitforms still filters spam and saves each accepted submission, so check required fields in your webhook handler before acting on a submission. Webhooks come with Pro ($5/month) or Annual ($49/year).

Simple pricing

How much does splitforms cost?

Free gives you 500 submissions for $0 — no card, no time limit. Pro is $5/month for 5,000 submissions a month, and Annual is $49/year for 15,000 a month with every Pro feature.

Free

$0— 500 submissions
 

No card, no time limit

Best for testing

For side projects and indie devs.

  • 500 free submissions
  • Unlimited forms
  • Email notifications included
  • Smart spam filtering
  • Submissions dashboard
  • Redirect after submit
  • MCP server included

Annual

$49/ year
About $4.08/mo, billed yearly
Best value

Every Pro feature with triple the volume — $0.27 per 1,000 at full use.

  • 15,000 submissions / mo
  • Unlimited forms
  • Everything in Pro
  • File uploads with 5 GB storage
  • 3 team seats
  • Priority email support

No credit card required on Free • Cancel anytime • Full pricing and FAQ