# 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 October 31, 2026

## 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.

```html
<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.

![The Peak Fitness form with an empty email box, outlined, and the browser's bubble below it saying "Please fill out this field": the form was not sent](https://www.ask-codey.com/lessons/TODO)

## 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.

```html
<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:

```html
<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:

```html
<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:

```html
<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.

## Key terms

- [required](https://www.ask-codey.com/glossary/required)
- [pattern](https://www.ask-codey.com/glossary/pattern)
- [min](https://www.ask-codey.com/glossary/min-html)
- [max](https://www.ask-codey.com/glossary/max-html)
- [minlength](https://www.ask-codey.com/glossary/minlength)
- [Constraint validation](https://www.ask-codey.com/glossary/constraint-validation)

## Cheat sheets

- [Built-in Validation](https://www.ask-codey.com/cheat-sheets/html-forms-built-in-validation-cheat-sheet)

## Related

- [Why the Server Checks Again](https://www.ask-codey.com/lessons/html-forms-why-the-server-checks-again)
- [Hints and Error Messages Everyone Can Use](https://www.ask-codey.com/lessons/html-forms-hints-and-error-messages)

Source: https://www.ask-codey.com/lessons/html-forms-built-in-validation
