HTML Guides for email
Learn how to identify and fix common HTML validation errors flagged by the W3C Validator — so your pages are standards-compliant and render correctly across every browser. Also check our Accessibility Guides.
The maxlength attribute provides built-in client-side validation that caps the number of characters a user can type into a field. Browsers enforce this by preventing further input once the limit is reached. However, this behavior only makes sense for input types that accept arbitrary text strings. Input types like number, date, range, and checkbox have their own value formats and constraints — a number input's value is controlled by min, max, and step, not by character count.
When you place maxlength on an unsupported input type, browsers will ignore the attribute. This means it provides no actual validation while giving a false sense of security. It also produces invalid HTML, which can cause issues with assistive technologies that may try to interpret the attribute and relay incorrect information to users. Keeping your markup valid ensures predictable behavior across browsers and a better experience for all users.
How to fix it
- Remove
maxlengthfrom any<input>whosetypeis notemail,password,search,tel,text, orurl. - Use the correct constraint attributes for the input type in question. For
numberinputs, useminandmax. Fordateinputs, useminandmaxwith date strings. - If you genuinely need character-length validation, consider whether a text-based input type is more appropriate for your use case, or implement the constraint in JavaScript.
Examples
❌ Invalid: maxlength on a number input
<labelfor="quantity">Quantity</label>
<inputtype="number"id="quantity"name="quantity"maxlength="3">
The number type does not support maxlength. Browsers will ignore it, and the HTML is invalid.
✅ Fixed: using min and max for a number input
<labelfor="quantity">Quantity</label>
<inputtype="number"id="quantity"name="quantity"min="0"max="999">
If the goal was to limit the value to three digits, min and max are the correct constraints.
❌ Invalid: maxlength on a date input
<labelfor="start-date">Start date</label>
<inputtype="date"id="start-date"name="start-date"maxlength="10">
Date inputs have a browser-provided date picker, and their values are always in YYYY-MM-DD format. The maxlength attribute has no effect here.
✅ Fixed: using min and max for a date input
<labelfor="start-date">Start date</label>
<inputtype="date"id="start-date"name="start-date"min="2020-01-01"max="2030-12-31">
❌ Invalid: maxlength on a checkbox
<label>
<inputtype="checkbox"name="agree"maxlength="1"> I agree
</label>
A checkbox is a boolean toggle — character length is meaningless here.
✅ Fixed: removing the invalid attribute
<label>
<inputtype="checkbox"name="agree"> I agree
</label>
✅ Valid: maxlength on supported text-based types
<labelfor="username">Username</label>
<inputtype="text"id="username"name="username"maxlength="30">
<labelfor="user-email">Email</label>
<inputtype="email"id="user-email"name="email"maxlength="254">
<labelfor="user-phone">Phone</label>
<inputtype="tel"id="user-phone"name="phone"maxlength="15">
<labelfor="site-url">Website</label>
<inputtype="url"id="site-url"name="website"maxlength="2048">
<labelfor="user-pass">Password</label>
<inputtype="password"id="user-pass"name="password"maxlength="128">
<labelfor="query">Search</label>
<inputtype="search"id="query"name="q"maxlength="100">
All six of these input types support maxlength because they accept free-form text where limiting character count is meaningful.
The minlength attribute defines the minimum number of characters (as UTF-16 code units) that a user can enter into a text-based input field. It provides built-in client-side validation without requiring JavaScript. However, it only makes sense on input types where the user is typing free-form text. For input types like number, date, color, range, or checkbox, the concept of a minimum character length doesn't apply — these inputs have their own constrained value formats or use other attributes like min and max for validation.
When the W3C validator encounters minlength on an unsupported input type, it flags the attribute as invalid. Browsers will typically ignore the attribute silently, meaning your intended validation won't actually work. This can lead to a false sense of security where you believe the input is being validated when it isn't.
The minlength value must be a non-negative integer (0 or higher) and must be less than or equal to maxlength if both are specified. The minlength attribute also works on <textarea> elements.
Examples
❌ Incorrect: minlength on a number input
The number input type doesn't support minlength. If you want to enforce a minimum value, use the min attribute instead.
<labelfor="age">Enter your age</label>
<inputtype="number"minlength="1"id="age">
✅ Fixed: Using min for number inputs
<labelfor="age">Enter your age</label>
<inputtype="number"min="1"id="age">
❌ Incorrect: minlength on a date input
<labelfor="start-date">Start date</label>
<inputtype="date"minlength="10"id="start-date">
✅ Fixed: Remove minlength from date inputs
Date inputs have a browser-controlled format, so character length constraints don't apply. Use min and max to constrain the date range.
<labelfor="start-date">Start date</label>
<inputtype="date"min="2024-01-01"id="start-date">
✅ Correct: minlength on supported input types
Here are valid uses of minlength across all supported input types:
<labelfor="username">Username (at least 3 characters)</label>
<inputtype="text"minlength="3"id="username">
<labelfor="email">Email</label>
<inputtype="email"minlength="5"id="email">
<labelfor="pass">Password (at least 8 characters)</label>
<inputtype="password"minlength="8"id="pass">
<labelfor="phone">Phone number</label>
<inputtype="tel"minlength="7"id="phone">
<labelfor="query">Search</label>
<inputtype="search"minlength="2"id="query">
<labelfor="website">Website URL</label>
<inputtype="url"minlength="10"id="website">
✅ Correct: minlength with maxlength on a textarea
<labelfor="bio">Bio (between 10 and 200 characters)</label>
<textareaminlength="10"maxlength="200"id="bio"></textarea>
Quick Reference
| Input Type | Supports minlength? | Alternative |
|---|---|---|
text, email, password, search, tel, url | ✅ Yes | — |
textarea | ✅ Yes | — |
number, range | ❌ No | Use min / max |
date, datetime-local, time, month, week | ❌ No | Use min / max |
checkbox, radio | ❌ No | Use required |
file | ❌ No | Validate with JavaScript |
color, hidden | ❌ No | Not applicable |
The pattern attribute provides a powerful way to add client-side form validation directly in HTML without relying on JavaScript. It accepts a regular expression that the browser uses to validate user input before the form is submitted. However, the HTML specification restricts pattern to input types where the user enters free-form text. Input types like number, date, range, color, and checkbox have their own built-in validation mechanisms (such as min, max, and step), so applying a regex pattern to them is meaningless and invalid.
When you add pattern to an unsupported input type, browsers will simply ignore it. This means you might think you have validation in place when you actually don't, which can lead to unexpected invalid data being submitted. Removing the invalid attribute also keeps your markup clean and standards-compliant, which benefits accessibility tools and future browser behavior.
Why certain types don't support pattern
number— Values are constrained bymin,max, andstep. The browser enforces numeric input natively.date,time,datetime-local,month,week— These use date/time pickers with their own format and range constraints.range— A slider control already constrained bymin,max, andstep.checkbox,radio— These are toggled on/off or selected from a group; a regex pattern doesn't apply.file— File selection is handled by the OS file picker; use theacceptattribute instead.color— Uses a color picker with a fixed hex format.hidden— Not user-editable, so client-side validation is irrelevant.
How to fix it
- Remove the
patternattribute if the input type already provides sufficient validation through its native controls. - Change the input
typeto one of the six supported types (email,password,search,tel,text, orurl) if you genuinely need regex-based validation. - Use alternative attributes like
min,max,step, oracceptthat are designed for the specific input type. - Use JavaScript validation if you need custom validation logic that goes beyond what native attributes offer.
Examples
❌ Incorrect: pattern on a number input
<labelfor="qty">Quantity (multiples of 5):</label>
<inputtype="number"id="qty"name="qty"pattern="[0-9]+"min="0"max="100">
The pattern attribute is not allowed on type="number". Since min, max, and step already handle numeric constraints, pattern is unnecessary here.
✅ Correct: using step instead of pattern for number validation
<labelfor="qty">Quantity (multiples of 5):</label>
<inputtype="number"id="qty"name="qty"min="0"max="100"step="5">
❌ Incorrect: pattern on a date input
<labelfor="dob">Date of birth:</label>
<inputtype="date"id="dob"name="dob"pattern="\d{4}-\d{2}-\d{2}">
The date input type already enforces a date format through its native picker, so pattern is invalid here.
✅ Correct: removing pattern from date input
<labelfor="dob">Date of birth:</label>
<inputtype="date"id="dob"name="dob"min="1900-01-01"max="2025-12-31">
❌ Incorrect: pattern on a checkbox input
<label>
<inputtype="checkbox"name="agree"pattern=".+"> I agree to the terms
</label>
✅ Correct: using required instead of pattern for checkbox
<label>
<inputtype="checkbox"name="agree"required> I agree to the terms
</label>
✅ Correct: pattern on a supported text input
<labelfor="zip">ZIP code:</label>
<inputtype="text"id="zip"name="zip"pattern="[0-9]{5}"title="Five digit ZIP code"required>
When using pattern on a supported input type, always include a title attribute that describes the expected format. Browsers display the title text as part of the validation error message, helping users understand what input is expected.
The required attribute is a boolean attribute that tells the browser a field must be filled in before the form can be submitted. However, not every input type supports this concept. Some input types always have a value (like range, which defaults to a midpoint, or color, which defaults to #000000), while others represent actions rather than user data (like submit, reset, image, and button). For hidden inputs, the user has no way to interact with the field at all, so requiring them to provide a value makes no sense.
The HTML specification explicitly limits required to the following input types: checkbox, date, datetime-local, email, file, month, number, password, radio, search, tel, text, time, url, and week.
Using required on an unsupported type is invalid HTML. Browsers will typically ignore the attribute in this situation, which means you might believe a field is required when it actually isn't being validated at all. This can lead to forms being submitted with missing or unexpected data. It also creates confusion for assistive technologies — screen readers may announce a field as required even though the browser won't enforce it, misleading users.
How to fix it
- Check the input type. If you're using
requiredon an input with a type likehidden,range,color,submit,reset,image, orbutton, the attribute is not allowed. - Remove the
requiredattribute if the input type inherently provides a value or doesn't accept user-provided data. - Change the input type if you actually need the field to be required and the current type doesn't match your intent.
- Use server-side validation for inputs like
hiddenthat can't userequiredbut still need a value.
Examples
❌ Invalid: required on a hidden input
<form>
<inputtype="hidden"name="token"required>
<buttontype="submit">Submit</button>
</form>
The user cannot interact with a hidden input, so required is not allowed here. The browser won't enforce it.
❌ Invalid: required on a range input
<form>
<labelfor="volume">Volume:</label>
<inputtype="range"id="volume"name="volume"min="0"max="100"required>
<buttontype="submit">Submit</button>
</form>
A range input always has a value (it defaults to the midpoint), so required is meaningless and not permitted.
❌ Invalid: required on a color input
<form>
<labelfor="color">Pick a color:</label>
<inputtype="color"id="color"name="color"required>
<buttontype="submit">Submit</button>
</form>
A color input always has a value (defaulting to #000000), so required is not valid here.
✅ Valid: required removed from unsupported types
<form>
<inputtype="hidden"name="token"value="abc123">
<labelfor="volume">Volume:</label>
<inputtype="range"id="volume"name="volume"min="0"max="100">
<buttontype="submit">Submit</button>
</form>
✅ Valid: required on supported input types
<form>
<labelfor="email">Email:</label>
<inputtype="email"id="email"name="email"required>
<labelfor="dob">Date of birth:</label>
<inputtype="date"id="dob"name="dob"required>
<label>
<inputtype="checkbox"name="terms"required>
I agree to the terms
</label>
<buttontype="submit">Submit</button>
</form>
These input types — email, date, and checkbox — all accept direct user input and are on the allowed list for the required attribute.
Validate at scale.
Ship accessible websites, faster.
Automated HTML & accessibility validation for large sites. Check thousands of pages against WCAG guidelines and W3C standards in minutes, not days.
Pro Trial
Full Pro access. Cancel anytime.
Start Pro Trial →Join teams across 40+ countries