send.webforms.toRead the docs →

HTML input pattern generator and tester

Pick a rule (numbers only, a UK postcode, an international phone number) and get the pattern attribute with the input around it: a title message, the right type and inputmode, and required if you want it. Then test it the way your browser compiles it, which since 2023 means the v flag, and is why plenty of patterns that used to work now do nothing. It all runs in your browser.

What should the field accept?

How many digits

type="number" is meant for quantities: it ignores pattern and accepts values like 1e5. Codes, card numbers and anything with leading zeros belong in a text input with inputmode="numeric", as here.

Edit it freely. The browser wraps it as ^(?:...)$, so it always has to match the whole value.

Compiles. The browser runs /^(?:[0-9]+)$/v

The field around it

field.html
<label for="code">Code</label>
<input
  id="code"
  name="code"
  type="text"
  inputmode="numeric"
  pattern="[0-9]+"
  title="Digits only"
  aria-describedby="code-hint"
  required
>
<p id="code-hint">Numbers only, no spaces or other characters.</p>

Test it

  • 0valid
  • 007valid
  • 123456valid
  • 12adoes not match
  • 1 2does not match
  • -5does not match
  • 1.5does not match
  • 123does not match

How the pattern attribute works

The browser does not use your pattern as written. It first checks that the pattern compiles on its own, then wraps it as ^(?:pattern)$ so it has to match the entire value, and compiles that with the v flag. You cannot add flags of your own, so matching is case-sensitive: [a-z]+ refuses ABC. The attribute applies to text, search, tel, url, email and password inputs. Give the field a title that describes the format, since browsers may show it when a value does not match, and a visible hint as well, because a title alone is easy to miss.

Why your HTML input pattern is not working

When a pattern seems to be ignored, it usually is. The common causes:

Numbers only, alphanumeric and phone numbers

For numbers only, [0-9]+ is all a pattern needs, or [0-9]{6} for exactly six digits. Pair it with inputmode="numeric" so phones show a digit keypad. For alphanumeric, [A-Za-z0-9]+. Patterns compile in Unicode mode, so \p{L} works too, and ticking "any alphabet" above keeps José and Ελένη from being turned away.

Phone numbers have no single right regex. If you store numbers in E.164, \+[1-9][0-9]{1,14} checks that shape: a plus, then at most fifteen digits. People rarely type numbers that way, though, so the loose preset accepts spaces, brackets, dots and hyphens and counts seven to fifteen digits. Normalise to one format on the server.

Server-side validation is still required

A pattern helps the person filling in the form. It does nothing about a bot, a script or anyone posting to your endpoint directly, because none of them run your HTML. Check the format again wherever the data is used. A pattern behaves the same in JavaScript as new RegExp(`^(?:${pattern})$`, "v"), and simple ones port to other languages unchanged.

If the form posts to WebForms, each submission is stored as it was sent and filtered for spam before anything is delivered. WebForms never sees your HTML, so it does not re-run the pattern attribute: a format that matters downstream needs checking where you use the data. For inline error messages instead of the browser's bubbles, start from the JavaScript validation form. To build the whole form, use the HTML form generator, and if it will not submit at all, the form debugger finds the usual causes. Email fields have trade-offs of their own: compare the common regexes in the email regex tester.

Sources