HTML Form Validation
Form validation means checking that the visitor filled in the form correctly before it is sent.
Why Validate in the Browser?
Without validation, a visitor can send an empty name, a phone number with letters, or an age of 500. HTML can catch these mistakes at once, with no JavaScript, and show a helpful message next to the field.
Browser validation is for the visitor's comfort. It is easy to skip, so the server must always check the data again before saving it.
The Validation Attributes
| Attribute | Works with | Rule |
|---|---|---|
required | Almost all fields | Must not be empty |
minlength, maxlength | Text, password, textarea | Shortest and longest text |
min, max | Number, date, range, time | Smallest and largest value |
step | Number, date, range | Allowed steps, e.g. step="500" |
pattern | Text, tel, email, password, url | Must match a regular expression |
type="email", type="url" | Email and web address fields | Must look like an email or URL |
A Form with Validation
Ayesha runs admissions for a short course. Her form needs a name, a valid email, an age between 15 and 60, and a CNIC number in the form 12345-1234567-1.
Example
<!DOCTYPE html>
<html>
<body>
<h2>Course Admission</h2>
<form>
<label for="name">Full name (3 to 40 letters):</label><br>
<input type="text" id="name" name="name" required minlength="3" maxlength="40"><br><br>
<label for="email">Email:</label><br>
<input type="email" id="email" name="email" required><br><br>
<label for="age">Age (15 to 60):</label><br>
<input type="number" id="age" name="age" min="15" max="60" required><br><br>
<label for="cnic">CNIC:</label><br>
<input type="text" id="cnic" name="cnic" placeholder="42101-1234567-1"
pattern="[0-9]{5}-[0-9]{7}-[0-9]" title="Format: 12345-1234567-1" required><br><br>
<button type="submit">Apply</button>
</form>
</body>
</html>Try it Yourself »Press Apply with empty or wrong fields. The browser stops at the first problem and shows a message. The title text is added to the pattern message, so tell the user the format you expect.
Understanding pattern
pattern uses a regular expression. The whole value must match. Here are some useful ones:
| Pattern | Accepts |
|---|---|
[0-9]{4} | Exactly 4 digits, like a PIN |
03[0-9]{9} | A Pakistani mobile number like 03001234567 |
[A-Za-z ]+ | Letters and spaces only |
[A-Z]{3}-[0-9]{3} | A car plate style code like KHI-123 |
Styling Valid and Invalid Fields
CSS can colour fields by their state. The :user-invalid selector only turns red after the user has typed in the field or tried to submit, so the form does not look wrong before they start.
Example
<!DOCTYPE html>
<html>
<head>
<style>
input { padding: 6px; border: 2px solid #999; border-radius: 4px; }
input:user-invalid { border-color: crimson; }
input:user-valid { border-color: seagreen; }
</style>
</head>
<body>
<form>
<label for="pin">4-digit PIN:</label><br>
<input type="text" id="pin" name="pin" pattern="[0-9]{4}" required>
<button type="submit">Save</button>
</form>
<p>Type "12a" and click outside the box, then type "1234".</p>
</body>
</html>Try it Yourself »| Selector | Matches |
|---|---|
:valid / :invalid | Any field that passes or fails, even before typing |
:user-valid / :user-invalid | Only after the user has interacted with it |
:required / :optional | Fields with or without required |
Turning Validation Off
Add novalidate to the form to skip all browser checks. This is useful while testing, or when JavaScript does its own checks.
Example
<form action="/apply" method="post" novalidate>
...
</form>You can also skip checks for one button only, such as "Save draft", with formnovalidate:
Example
<button type="submit">Apply</button>
<button type="submit" formnovalidate>Save draft</button>Helping the Browser Autofill
The autocomplete attribute tells the browser what a field is, so it can fill in saved details and make forms faster on phones.
Example
<input type="text" name="name" autocomplete="name">
<input type="email" name="email" autocomplete="email">
<input type="tel" name="phone" autocomplete="tel">
<input type="password" name="pwd" autocomplete="current-password">Exercise
Exercise
Which attribute makes an age field accept only values from 18 to 30?
