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?
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
<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
0valid007valid123456valid12adoes not match1 2does not match-5does not match1.5does not match123does 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:
- It is not valid under the v flag. Since 2023 the HTML standard compiles patterns with
vinstead ofu. Chrome switched in version 114, and WebKit, the engine behind Safari, made the same change that year. Inside a character class,vrequires(,),[,{,},/,-and|to be escaped and refuses doubled punctuation such as!!. So[0-9+()\- ]+and[\w-]+, both fine for years, are now syntax errors, and an invalid pattern is dropped without a word to the visitor. Browsers are encouraged to log it in the developer console, and the tester above offers the escaped version. - It was pasted from JavaScript.
pattern="/^[0-9]+$/"asks for a value that starts and ends with a slash. Drop the slashes and any flags. The anchors can stay, though they are redundant. - The input is type="number". Number, date, time and the other non-text types ignore pattern entirely. For digit codes, use
type="text"withinputmode="numeric". - The field is empty. An empty value skips the pattern and the length checks. Add
requiredif it must be filled in. - Validation is switched off.
novalidateon the form orformnovalidateon the submit button skips it, and so doesform.submit()called from script, which submits without validating or firing a submit event.form.requestSubmit()validates first. - The length rule lives elsewhere.
minlengthandmaxlengthare checked separately from the pattern, and only once the visitor has edited the field, so a value set by script will not trip them.
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.