How do I validate a form without JavaScript?
Use required, type, min, max, minlength, maxlength and pattern. The browser enforces them before submitting, with no code at all — but you still need server-side validation.
<form>
<label for="email">Email</label>
<input type="email" id="email" name="email" required
autocomplete="email" maxlength="120">
<label for="age">Age</label>
<input type="number" id="age" name="age" required min="13" max="120">
<label for="username">Username</label>
<input type="text" id="username" name="username" required
pattern="[A-Za-z][A-Za-z0-9_]{2,15}"
title="Start with a letter, 3–16 characters">
<button>Sign up</button>
</form>#What you get free
- Submission is blocked until the constraints pass.
- Error bubbles, translated into the user's language.
- The right mobile keyboard from
type—emailgives an @ key,numbergives a keypad. autocompletelets password managers and browser autofill work.:invalidand:validCSS hooks.
#Style the states carefully
input:user-invalid { border-color: crimson; }Use :user-invalid rather than :invalid. Plain :invalid matches an empty required field on page load, so every form starts covered in red before the user has typed anything.
#Custom messages
input.addEventListener('invalid', () => {
input.setCustomValidity('We need an email to send your receipt.');
});
input.addEventListener('input', () => input.setCustomValidity(''));Clearing it on input is required — otherwise the field stays permanently invalid.
#Where HTML validation stops
It cannot check anything the browser does not know: whether a username is taken, whether two passwords match, whether a date is a business day. And it can be bypassed entirely with DevTools or curl.
#The title attribute is not an error message
Browsers append title to the pattern failure message, but it also shows as a tooltip and is unreliable for screen readers. Put the real explanation in visible text next to the field.