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.

JavaScript · EXAMPLE
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

  1. Stop this practice form’s submission.
  2. Remove feedback from the previous check.
  3. Evaluate every field, retaining the person’s entries.
  4. Display specific errors and mark affected fields.
  5. 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)

Original explanation and example prepared for HTML code FYI with AI assistance. Test the code in your own context. How these guides are made.