Built-in Validation
A few HTML attributes let the browser check a form's answers before it sends them, so people fix a missing email or a short ZIP code right away, with no JavaScript.
Apprentice · HTML · Web Development · Updated
After this lesson you can
- Add the built-in validation rules required, min, max, minlength, maxlength and pattern to a form's fields
- Predict whether the browser accepts a value, given a field's type and its rules
Key takeaways
- The browser checks a form's answers when someone sends it. If one breaks a rule, it stops, shows a message beside that field, and sends nothing.
- required means the field can't be left empty. An empty field that isn't required passes every other rule.
- min, max and step set the allowed numbers and dates; minlength and maxlength set how many characters a text answer may have.
- pattern is a rule for the shape of a text answer, such as [0-9]{5} for a five-digit ZIP code. The whole answer must match.
- The types email, url and number check their own format, with no rule written.
Peak Fitness, a made-up gym, gets sign-ups with no email address, ZIP codes with four digits and birth dates in the year 3026. Each one means a staff member phoning someone to ask again, or a new member who never hears back. You can stop most of those mistakes before the form is sent, with a few HTML attributes and no JavaScript. Any form you build for a sign-up, a checkout or a class project can use them.
The browser checks before it sends
Think of a clerk at the front desk who glances over a paper form before you walk away: "You missed the phone number." The browser can be that clerk. You give a field a rule, and when someone sends the form, the browser checks every field against its rules first.
This is called built-in validation. Validation means checking that an answer is acceptable. In the HTML standard, and in some textbooks, it's called constraint validation: each rule is a constraint, a limit on what the field accepts.
<form action="received.html">
<label for="email">Email</label>
<input type="email" id="email" name="email" required>
<button type="submit">Join Peak Fitness</button>
</form>
Press Join Peak Fitness with the email box empty, and nothing is sent. The browser jumps to the box and shows a message in a small bubble. In Chrome it says Please fill out this field. Each browser words its messages its own way, in the language the person's computer uses.
required: an answer you must have
required is a boolean attribute: its name alone switches it on, with no value. A required field can't be left empty, and for a checkbox, it must be checked.
<label for="full-name">Full name</label>
<input type="text" id="full-name" name="fullName" required>
<input type="checkbox" id="terms" name="terms" value="agreed" required>
<label for="terms">I agree to the membership terms</label>
Be careful with required="false". It still means required: the browser sees the attribute's name and ignores the value. To make a field optional, leave required out.
One more thing that surprises people: a field that isn't required may be left empty, and an empty field passes every other rule. The rules below check an answer only when there is one.
Numbers and dates: min, max and step
min and max set the smallest and largest answer a number or date field accepts. Peak Fitness sells personal-training sessions in packs of four, from 4 to 20, and new members can start any day in the next two months:
<label for="sessions">Training sessions</label>
<input type="number" id="sessions" name="sessions" min="4" max="20" step="4">
<label for="start-date">Start date</label>
<input type="date" id="start-date" name="startDate" min="2026-11-01" max="2026-12-31">
step sets the size of each jump between allowed values, counting from min. Here the allowed numbers are 4, 8, 12, 16 and 20, so 10 is refused. A number field's step is 1 unless you change it, which is why 2.5 is refused in a plain type="number" field. For prices, write step="0.01".
Dates are written year, month, day (2026-11-01), however the date picker shows them on the screen.
Text length: minlength and maxlength
minlength and maxlength count the characters in a text answer. Peak Fitness wants passwords of at least 8 characters, and a nickname for the class leaderboard of at most 20:
<label for="password">Password</label>
<input type="password" id="password" name="password" minlength="8" required>
<label for="nickname">Leaderboard nickname</label>
<input type="text" id="nickname" name="nickname" maxlength="20">
The two behave differently. maxlength stops the typing: after 20 characters, the box takes no more. minlength lets people type anything, then complains when the form is sent: Chrome says something like Please lengthen this text to 8 characters or more (you are currently using 4 characters).
Try it. In VS Code, make a file named validation.html with the page skeleton (type ! and press Tab), and put the password field and a button in a <form>. Open it with Live Server, type tuba, and press the button. Then type purple-otter-tuba and press it again.
pattern: the shape of an answer
Some answers have a shape. A US ZIP code is five digits: 30301, never 3030 or 30301-ABC. pattern gives a field that shape:
<label for="zip">ZIP code</label>
<input type="text" id="zip" name="zip" pattern="[0-9]{5}">
[0-9]{5} is read "any digit from zero to nine, five times". The square brackets [ ] hold the characters allowed in one place: [0-9] is one digit. The curly braces { } say how many times: {5} is exactly five.
The browser checks the whole answer against the pattern, so 303011 is refused as well as 3030. The language a pattern is written in is called a regular expression. It goes much further than this, but [0-9], [A-Z] (one capital letter) and {n} cover most of what a form needs. A few more you may see: {2,4} means two to four times, and [A-Za-z] means one letter of either case.
pattern works on text-like fields: text, tel, email, url, search and password. When an answer doesn't match, Chrome says Please match the requested format., which doesn't tell anyone what the format is. Hints and Error Messages Everyone Can Use shows how to fix that with a hint.
The type checks for you
Some input types bring a rule of their own, with no attribute written:
| Type | Accepted | Refused |
|---|---|---|
email |
sam.rivera@example.com, and also sam@gym |
sam.example.com (no @) |
url |
https://peakfitness.example |
peakfitness.example (no https://) |
number |
12, -3 |
most letters (Chrome won't let you type them, apart from e, as in 3e5; other browsers refuse them when the form is sent) |
Notice that sam@gym passes: the email check looks for a name, an @ and something after it, not a real address. Only sending an email proves an address works.
The browser checks everything when the form is sent: every field, top to bottom, stopping at the first one that breaks a rule. A stylesheet can also color a field that breaks a rule while someone types, with :invalid (if you want to write styles like that, the CSS in Depth course teaches CSS from the start).
Check yourself
2 questions to try on the lesson page.
So what
Six attributes and the right types catch most of the mistakes people make on a form, at the moment they can still fix them. That's fewer phone calls for the gym, and fewer people who give up.