Forms as workflows
A form should guide the user clearly. It should explain what is needed, what format is expected, and what happened after submission.
Labels and inputs
Every input needs a connected label. The label’s for attribute should match the input’s id. This improves accessibility and makes the input easier to click.
Input types and constraints
Use the right input type: email, password, number, url, search, tel, date, and textarea. Correct types improve mobile keyboards and browser validation. Add constraints such as required, minlength, maxlength, min, and max where they describe real requirements.
Validation messages
Good error messages are specific and actionable. “Password must be at least 8 characters” is better than “Invalid input.” Place feedback close to the related field and provide a status message after submission so the outcome is not left ambiguous.
Security
Client-side validation improves user experience but can be bypassed. Real applications must validate and sanitise data on the server. Never treat a disabled button, hidden field, or browser check as a security boundary. The browser belongs to the user and can be modified.
Accessible feedback
When JavaScript updates a success or error message, a live region can announce that change to assistive technology. Use a nearby element with role="status" for general updates. If a field is invalid, explain the issue in text and move focus only when it genuinely helps the user fix the problem.
Example code
const form = document.querySelector("#contact-form");
const email = document.querySelector("#email");
const message = document.querySelector("#form-message");
form.addEventListener("submit", (event) => {
event.preventDefault();
if (!email.value.includes("@")) {
message.textContent = "Enter an email address that includes @.";
email.focus();
return;
}
message.textContent = "Thanks. Your message is ready to send.";
});
Applied example: HTML constraints with a status message
Start with useful HTML. JavaScript can enhance the feedback after the browser understands the basic requirements.
<form id="contact-form">
<label for="email">Email address</label>
<input id="email" name="email" type="email" required>
<label for="message">Message</label>
<textarea id="message" name="message" minlength="20" required></textarea>
<button type="submit">Send enquiry</button>
<p id="form-status" role="status"></p>
</form>
Guided example: how to approach this lesson
Use these steps as a practical build process. The goal is not just to read the concept, but to know exactly how to apply it in your own page.
Step 1: Create the form structure
Add a form element, labels, inputs, a submit button, and a message area.
Step 2: Use HTML validation first
Add required, type, minlength, maxlength, and other built-in constraints where appropriate.
Step 3: Add JavaScript feedback
Use JavaScript to display clearer error messages and guide the user to the field that needs attention.
More examples
Compare these examples carefully. The improved version shows the kind of code pattern you should aim for when building your own project.
Weak form field
<input placeholder="Email">
This is weak because the input has no connected label and the browser does not know it expects an email address.
Better form field
<label for="email">Email address</label>
<input id="email" name="email" type="email" required>
<p id="email-help">Use the address you check most often.</p>
This is clearer, more accessible, and gives the browser useful validation information.
Before moving on
Use this checklist to make sure you understand the lesson well enough to apply it without copying blindly.
- Does every input have a label?
- Are the correct input types used?
- Are error messages specific?
- Does the user know what to fix?
Common mistakes to avoid
- Using placeholders instead of labels.
- Showing vague errors.
- Only using colour to show errors.
- Assuming client-side validation is secure.
Practice task
Create a contact form for the homepage and make every validation decision understandable.
Required outcome
- Add name, email, topic, and message fields with connected labels and suitable input types.
- Use HTML constraints first, including
requiredand a sensible messageminlength. - Add a submission status element with
role="status". - Use JavaScript to stop submission, display an actionable result, and focus the first field that needs correction.
Stretch goal: Add a remaining-character count for the message without preventing keyboard use.