Understand the idea
Validation is a conversation about what a field needs. A message such as “Invalid input” identifies very little; a message such as “Write at least 10 characters” explains a fix.
HTML can express requirements such as required and type="email". JavaScript can inspect validity and add rules. A real receiving service must validate again: browser checks can be bypassed, and passing an email syntax check does not prove that an address exists.
Read the example
A focused excerpt, not a complete form. It requires a labelled textarea with id="message" and aria-describedby="message-error", plus an existing element with id="message-error". The complete recipe coordinates all fields and intercepts submission.
const message = document.querySelector('#message');
const error = document.querySelector('#message-error');
const tooShort = message.value.trim().length < 10;
error.textContent = tooShort ? 'Write at least 10 characters.' : '';
if (tooShort) {
message.setAttribute('aria-invalid', 'true');
message.focus();
} else {
message.removeAttribute('aria-invalid');
}Choose a validation approach deliberately
Native browser messages are a useful default. A custom system takes on extra responsibilities: explaining every failed rule, associating messages with fields and managing focus. Use novalidate only when you are providing that alternative. It disables the browser’s automatic submission validation, not the validity information available to scripts.
A predictable sequence
- Stop this practice form’s submission.
- Remove feedback from the previous check.
- Evaluate every field, retaining the person’s entries.
- Display specific errors and mark affected fields.
- Focus the first invalid field, or report that this local check passed.
Do not interrupt every keystroke with a new error. Let a visitor finish entering a value; clear stale feedback when they change it. For larger forms, an error summary with links to invalid fields can make recovery easier.
What is being measured?
The example’s JavaScript length rule counts UTF-16 code units, not necessarily visible characters. It is suitable for demonstrating a simple rule, but product requirements involving names, complex emoji or exact user-perceived character counts need a more deliberate definition.
A check is not a submission
Try the form without sending. It has no delivery endpoint and blocks form submission through its document policy. Real services need a separate server-side design, honest delivery feedback and a reason for collecting each field.
A small mistake, explained
What goes wrong
An error appears only as colour, or the page announces success even though no delivery took place.
How to fix it. Write a specific error near the field, connect it with aria-describedby, set aria-invalid when appropriate and distinguish successful checking from successful delivery.
Try it yourself
Use the practice recipe with empty input, an incomplete email address and a message containing only spaces. Then correct each entry and check that old feedback disappears.
Further reading
MDN: Constraint validation (new tab)
Keep exploring
- HTML · Guide
Your first HTML documentGive the browser a clear document, from the doctype to the closing tag.
- HTML · Guide
Headings & paragraphsBuild a readable outline instead of choosing tags by their default size.