← HTML and CSS fundamentals: structure, presentation and diagnosis
04 / 10 · 65 MIN

Constraints, feedback and accessibility

Interpret native constraints and the limits of each validation path. Communicate usable errors while retaining server checks.

Constraints expressed in HTML

Control type defines part of the local contract. In the example, email checks a format and required requires a value. Required is Boolean: its presence retains the requirement even when the attribute text is false.

Remove the attribute to remove the requirement. Browser message presentation can vary. The result remains limited to local constraints and confirms neither mailbox existence nor authorization to request capacity.

Range and alignment

The numeric input admits a grid: start at 2 and advance by 2 up to 10. The value 3 is not outside the limits but fails step alignment. These are different diagnoses with different corrections.

If the business rule permits any number in range, configuration should reflect that policy; a constraint should not be removed merely because one example failed. The server should apply the same relevant contract.

A custom message has state

setCustomValidity represents an additional rule through a nonempty message. That message retains the error until cleared. When the condition stops failing, call setCustomValidity with an empty string; writing OK or valid still retains a custom error.

For a relationship between two fields, reevaluate when any relevant dependency changes. Clearing that error does not bypass remaining control constraints or server rules.

The validation path matters

checkValidity returns a result about applicable constraints; reportValidity also reports failures to the user. Normal submission can trigger interactive validation, but novalidate and certain paths alter that behavior. A value assigned by code does not necessarily receive the same checks as human editing: minlength and maxlength are not checked for programmatic assignments through that path, even when calling these APIs. Validate imports explicitly against the contract.

Starting submission from code

requestSubmit follows a submitter path, respecting validation conditions and the submit event. Direct submit skips constraint validation and does not fire that event. If a keyboard shortcut must retain visible-button behavior, the distinction is decisive.

Constructing FormData only prepares data; it does not prove submission occurred. When interpreting an excerpt, identify the actual call before concluding that every step ran.

An error that can be located and corrected

A useful message identifies the field and explains what should change. After a failed submission, a summary linking to controls can help restore context. Associate descriptions with fields and consider focusing the first error without repeatedly moving focus while another field is being corrected. aria-invalid communicates an error state to assistive technology; it does not replace the rule deciding whether to accept or reject the operation.

Complete operation acceptance

A visual valid indication may mean only that known browser constraints passed. The API can still reject the request because capacity is unavailable or current data conflicts. Retain that distinction in feedback: do not present an operation as complete before receiving evidence of that outcome.

When answering cases, explain the rule, path and available observation. Assessment requires interpreting these relationships rather than executing code or contacting a server.

<form action="/pedidos/capacidade" method="post">
  <label for="contacto">Email de contacto</label>
  <input id="contacto" name="contacto" type="email" required
         aria-describedby="contacto-ajuda">
  <p id="contacto-ajuda">Indica o email para receber a decisão.</p>
  <label for="unidades">Unidades</label>
  <input id="unidades" name="unidades" type="number"
         min="2" max="10" step="2" required aria-describedby="unidades-ajuda">
  <p id="unidades-ajuda">Escolhe 2, 4, 6, 8 ou 10 unidades.</p>
  <button type="submit">Pedir capacidade</button>
</form>
IN PRACTICE

The fictional form requires email and a unit count. Three units fall between 2 and 10 but violate step. Acceptance of email format does not prove mailbox existence.

Markup supplies associated help; it includes no server, error response or persistence. The actual capacity rule would need confirmation at the endpoint.

Common pitfalls

Using required="false" to disable a requirement; treating email format as identity proof; leaving positive text in setCustomValidity; trusting maxlength on programmatic assignment; expecting aria-invalid to prevent submission; replacing messages with color.

Related topics: Forms, controls and submission · Focus, states, motion and user preferences · Diagnosing styles and delivery

Take this idea with you

Each check has a scope. Native validation helps during interaction, feedback explains correction and the server decides actual acceptance. Keep all three connected to the same contract and explicitly identify paths skipping steps.

Create account

Reference: Client validation and server acceptance · HTML Living Standard; modular CSS