← All articles
HTMLValidationForms

HTML form validation: a complete guide

FormsFort Team ·

Form validation ensures users provide correct, complete data before submission. HTML5 provides a comprehensive set of validation attributes that work natively in every modern browser, without any JavaScript.

This guide covers every validation attribute, how to combine them, and when to add custom validation on top.

HTML5 validation attributes

required

The required attribute prevents form submission when the field is empty:

<input type="text" name="name" required />

The browser shows a tooltip like “Please fill out this field” when the user tries to submit.

type

The input type attribute provides built-in format validation:

TypeValidates
emailValid email format (contains @ and domain)
urlValid URL format
numberNumeric value only
telPhone number (optimizes mobile keyboard, no strict format)
dateValid date format
timeValid time format
<input type="email" name="email" required />
<input type="url" name="website" />
<input type="number" name="quantity" min="1" max="100" />

minlength and maxlength

Restrict the character count of text inputs:

<input type="text" name="username" minlength="3" maxlength="30" required />
<textarea name="bio" minlength="10" maxlength="500"></textarea>

min and max

Restrict numeric ranges:

<input type="number" name="age" min="18" max="120" />
<input type="date" name="appointment" min="2026-01-01" />
<input type="range" name="rating" min="1" max="5" />

step

Control the increment for numeric inputs:

<input type="number" name="price" min="0" step="0.01" />
<input type="time" name="meeting" step="900" />

pattern

The pattern attribute accepts a JavaScript regular expression:

<input type="text" name="zip" pattern="[0-9]{5}" title="Enter a 5-digit ZIP code" required />

Always include a title attribute with pattern so the browser can show a helpful error message.

Common validation patterns

Email with domain restriction

<input
type="email"
name="email"
pattern="^[^@\s]+@company\.com$"
title="Use your @company.com email address"
required
/>

Phone number (international)

<input
type="tel"
name="phone"
pattern="\+?[0-9\s\-\(\)]{7,20}"
title="Enter a valid phone number"
/>

URL with protocol

<input
type="url"
name="website"
pattern="https?://.+"
title="Enter a URL starting with http:// or https://"
/>

Password strength

<input
type="password"
name="password"
minlength="8"
pattern="(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9]).{8,}"
title="At least 8 characters with uppercase, lowercase, and a number"
required
/>

US ZIP code

<input
type="text"
name="zip"
pattern="[0-9]{5}(-[0-9]{4})?"
title="Enter a 5-digit or 9-digit ZIP code"
/>

Styling validation states with CSS

Browsers apply pseudo-classes to inputs based on their validation state:

input:valid {
border-color: #22c55e;
}
input:invalid {
border-color: #ef4444;
}
input:required {
border-left: 3px solid #059669;
}
input:user-invalid {
border-color: #ef4444;
background: #fef2f2;
}

The :user-invalid pseudo-class (supported in modern browsers) only applies after the user has interacted with the field, avoiding red borders on page load.

Custom validation with JavaScript

For validation logic that goes beyond what HTML attributes can express, use the Constraint Validation API:

const email = document.getElementById("email");
email.addEventListener("input", () => {
if (email.validity.typeMismatch) {
email.setCustomValidity("Please enter a valid email address.");
} else if (email.value && !email.value.endsWith("@company.com")) {
email.setCustomValidity("Only @company.com addresses are allowed.");
} else {
email.setCustomValidity("");
}
});

Call setCustomValidity("") with an empty string to clear the error and mark the field as valid.

Checking validity before submission

document.querySelector("form").addEventListener("submit", (e) => {
const form = e.target;
if (!form.checkValidity()) {
e.preventDefault();
form.reportValidity();
}
});

Disabling native validation

To disable HTML5 validation entirely (useful when implementing custom validation UI):

<form novalidate>
<!-- fields -->
</form>

With novalidate, the form submits regardless of validation state. You handle all validation in JavaScript.

Server-side validation

Client-side validation improves user experience but can be bypassed. Always validate on the server or form backend as well:

  • Type checking: Ensure email fields contain valid emails
  • Length limits: Enforce maxlength server-side
  • File validation: Check MIME types, file sizes, and scan for malware
  • Domain restrictions: Only accept submissions from allowed origins
  • Rate limiting: Prevent abuse from a single IP

A form backend service like FormsFort handles server-side validation automatically, including MIME type checking, file scanning, and domain restriction enforcement.

Accessibility considerations

  • Always associate <label> elements with inputs using the for attribute
  • Use aria-describedby to link error messages to their fields
  • Use aria-invalid="true" on fields that fail validation
  • Use aria-live="polite" on error message containers so screen readers announce changes
<label for="email">Email</label>
<input type="email" id="email" name="email" required aria-describedby="email-error" />
<span id="email-error" role="alert" aria-live="polite"></span>

Summary

HTML5 provides a complete validation system that works without JavaScript. Use required, type, pattern, minlength, maxlength, min, max, and step to validate most form inputs. Style validation states with CSS pseudo-classes. Add custom JavaScript validation with the Constraint Validation API when HTML attributes are not sufficient. Always enforce validation on the server side or through your form backend service.

Frequently asked questions

What is HTML form validation?

HTML form validation uses built-in browser attributes like required, type, pattern, minlength, and maxlength to check user input before submission. The browser prevents form submission and shows error messages when validation fails.

Can I validate forms without JavaScript?

Yes. HTML5 validation attributes work natively in all modern browsers without any JavaScript. The browser handles validation checks and displays error messages automatically.

What is the pattern attribute in HTML forms?

The pattern attribute accepts a regular expression that the input value must match. For example, pattern='[A-Z]{3}' requires exactly three uppercase letters.

How do I show custom validation messages in HTML?

Use the title attribute alongside pattern to provide a custom message. For more control, use JavaScript with the Constraint Validation API and setCustomValidity().

Should I validate on the client and server?

Yes. Client-side validation improves user experience by catching errors immediately. Server-side validation (or form backend validation) is essential for security because client-side checks can be bypassed.

Get started free

Ready to add forms to your static site?

No backend required. Point your HTML form at FormsFort and start receiving submissions in minutes.