Browser validation

Patterns and formats

Use native type validation and regular-expression patterns only when the accepted format is narrow, stable, and clearly explained.

Start with a native type. type="email" and type="url" already check the shape of the value and give you the right keyboard on a phone. Most forms need nothing more.

Reach for pattern only when the format is narrow and never changes. A project code is a good example. Say it’s always three uppercase letters, a dash, and four digits:

<label for="project">Project code</label>
<p id="project-help">Use the format ABC-1234.</p>
<input
  id="project"
  name="project"
  pattern="[A-Z]{3}-[0-9]{4}"
  aria-describedby="project-help"
  required
>

pattern takes a regular expression. The browser matches it against the whole value, so you don’t write ^ and $. ABC-1234 passes. abc-1234 and ABC-12345 fail.

Notice the help paragraph. A pattern is invisible to the person filling in the form. Tell them the format in plain words before they submit, not after.

Add a title

The browser’s default error for a pattern is “Please match the requested format”. That’s useless on its own. Add a title attribute and the browser appends it to the message:

<input pattern="[A-Z]{3}-[0-9]{4}" title="Three uppercase letters, a dash, and four digits">

Where patterns go wrong

Don’t write regular expressions for names, postal addresses, phone numbers, or email addresses. Real values are far more varied than you expect.

Names contain apostrophes, spaces, hyphens, and characters outside ASCII. Postal codes differ by country. Phone numbers come with or without country codes, spaces, and dashes. Every strict pattern I’ve seen for these blocks real people and stops no attacker.

For email, type="email" is already the right check. A stricter regex only rejects valid addresses.

Format is not meaning

ABC-1234 matches the pattern. That doesn’t mean project ABC-1234 exists, or that this user is allowed to see it. Checking the format is syntax. Checking that the project exists is meaning, and only the server can do it.

The server repeats the syntax check too

Browser validation can be skipped. Someone can submit project=DROP TABLE without ever loading your page. The server must apply the same regular expression before doing anything with the value.

Keep the pattern in one place if you can, and use it in both the HTML and the server code. Two copies drift apart.

Before adding a pattern, try this: write down five values that must pass and five that must fail. If you can’t explain the rule in one sentence, or if it rejects any of your plausible inputs, use a looser constraint and check the meaning on the server instead.

Lesson completed