📝 Phase 5 · Forms🟡 IntermediateModule 06
Form Validation
Course Progress57% complete
HTML5 ships a complete validation engine that runs before the form ever reaches your server. With the right attributes you can enforce required fields, minimum lengths, number ranges, and custom regex patterns — all without writing a single line of JavaScript. You also get CSS hooks to style valid and invalid states in real time.
Section 1
Validation Attributes
These attributes define the rules — the browser enforces them automatically on submit.
| Attribute | Works with | What it validates |
|---|---|---|
required | All inputs, select, textarea | Field must not be empty before submitting |
minlength | text, email, password, search, url, tel | Minimum number of characters |
maxlength | text, email, password, search, url, tel | Maximum number of characters (hard limit — prevents typing more) |
min | number, range, date, time | Minimum allowed value |
max | number, range, date, time | Maximum allowed value |
pattern | text, email, url, tel, search | Value must match this regular expression |
type | All | Built-in format validation (email must have @, url must have protocol, etc.) |
HTMLValidation attributes in action
<!-- Required + length limits --> <input type="text" name="username" required minlength="3" maxlength="20"> <!-- Email type validates format automatically --> <input type="email" name="email" required> <!-- Number with min/max range --> <input type="number" name="age" min="18" max="120" required> <!-- Pattern: UK postcode --> <input type="text" name="postcode" pattern="[A-Z]{1,2}[0-9][0-9A-Z]?\s?[0-9][A-Z]{2}" title="Enter a valid UK postcode e.g. SW1A 1AA" required>
💡
Always pair pattern with title
When a pattern fails, browsers show a generic "Please match the requested format" message. The
title attribute text is shown alongside it to explain what format is expected. Without it, users are left guessing.Section 2
Live Demo — Try It
Type into the fields below and watch the border change colour as you go — green when valid, red when invalid.
Border turns green when 3+ characters entered
Must contain @ and a valid domain
Enter a number outside 18–120 to see the red state
CSSStyling valid and invalid states
/* Only style after the user has interacted — */ /* :placeholder-shown = input is still empty */ input:valid:not(:placeholder-shown) { border-color: #2de8c0; /* green border */ background: rgba(45,232,192,.05); } input:invalid:not(:placeholder-shown) { border-color: #f87171; /* red border */ background: rgba(248,113,113,.05); }
:valid — field passes all rules
:invalid — field fails a rule
Section 3
Custom Error Messages
The browser's built-in error bubbles are functional but plain. You can intercept the validation event with JavaScript and show custom messages using the Constraint Validation API:
HTML + JSCustom validation messages
<form id="myForm" novalidate> <label for="em">Email</label> <input type="email" id="em" name="email" required> <span id="emErr" class="error"></span> <button type="submit">Submit</button> </form> <script> const form = document.getElementById('myForm'); form.addEventListener('submit', e => { const input = document.getElementById('em'); const err = document.getElementById('emErr'); if (!input.validity.valid) { e.preventDefault(); if (input.validity.valueMissing) err.textContent = 'Email is required.'; else if (input.validity.typeMismatch) err.textContent = 'Please enter a valid email.'; } else { err.textContent = ''; } }); </script>
🧠
validity state flags you can check
valueMissing (required empty) · typeMismatch (wrong format) · patternMismatch · tooShort / tooLong · rangeUnderflow / rangeOverflow · valid (all rules pass)Section 4
novalidate & Server Validation
Adding novalidate to the <form> element disables all browser validation — useful when you're writing your own JavaScript validation or using a form library. The inputs still carry their constraints for the Constraint Validation API to read; the browser just won't block submission.
🔒
Browser validation is a UX layer, not security
Anyone can disable browser validation with DevTools or by sending a crafted HTTP request. Always validate input on the server too. HTML validation improves user experience and reduces bad submissions — it does not prevent malicious data from reaching your server.
HTMLnovalidate for custom JS validation
<!-- Browser skips its own validation --> <!-- but all HTML5 constraint attributes still work via JS API --> <form action="/submit" method="post" novalidate> <input type="email" name="email" required> <!-- Your JS checks input.validity.* and shows your own UI --> <button type="submit">Submit</button> </form>
🧩 Quick Check — Lesson 20
5 questions · instant feedback
1. Which attribute makes a text input reject values shorter than 8 characters?
2. Which CSS pseudo-class matches an input that currently fails its validation rules?
3. Why is it common to combine :invalid with :not(:placeholder-shown)?
4. Is HTML5 form validation sufficient to protect your server from bad data?
5. What does the pattern attribute accept?
🏆
Quiz Complete!
Form validation done! Final forms lesson: select dropdowns and textarea.
Lesson 20 Challenge
Code exercise · 20 min
Build a validated registration form with custom CSS feedback states.
Create a sign-up form with these validated fields:
- Username: required, minlength 4, maxlength 16, pattern
- Email: type="email", required
- Password: type="password", required, minlength 8
- Age: type="number", min 13, max 120, required
CSS requirements:
- Inputs show a green border + subtle background when :valid (and not empty)
- Inputs show a red border when :invalid (and not empty)
- A ✓ or ✗ icon appears after each input using ::after on a wrapper
- The submit button is semi-transparent until the form is :valid (use form:valid + button styling)
Create a sign-up form with these validated fields:
- Username: required, minlength 4, maxlength 16, pattern
[a-zA-Z0-9_]+ (alphanumeric + underscore only)- Email: type="email", required
- Password: type="password", required, minlength 8
- Age: type="number", min 13, max 120, required
CSS requirements:
- Inputs show a green border + subtle background when :valid (and not empty)
- Inputs show a red border when :invalid (and not empty)
- A ✓ or ✗ icon appears after each input using ::after on a wrapper
- The submit button is semi-transparent until the form is :valid (use form:valid + button styling)
Show hints
- Use
:invalid:not(:placeholder-shown)to avoid red styling on pristine empty inputs - For form:valid button:
form:valid button[type=submit] { opacity: 1; background: ...; } - Icons via CSS: wrap input in a div, add
position: relativeand use ::after with content: '✓' or '✗' - Pattern
[a-zA-Z0-9_]+means: one or more chars from that set — the browser anchors it automatically