A collection catalog uses short shelf codes containing letters, digits, and hyphens. Its old expression worked in one JavaScript utility but fails after being copied into HTML. The problem can be the expression's syntax or how the string reached the attribute, rather than the text the cataloger entered.
Start with a visible rule and a small acceptance set
This illustrative shelf-code rule accepts 3–12 ASCII letters, digits, or hyphens:
<label for="shelf">Shelf code</label>
<input id="shelf" name="shelf" type="text"
pattern="[A-Za-z0-9\-]{3,12}"
aria-describedby="shelf-rule" required>
<p id="shelf-rule">
Use 3–12 letters A–Z, digits, or hyphens. No spaces.
</p>
AB-4 should match. AB 4 should fail. AB should fail because it is too short. An empty value fails required; it is not a pattern mismatch. These expectations describe this catalog's example rule, not a universal standard for identifiers.
There is no need to add ^ and $ just to prevent a substring match. The browser already requires the entire value to match. Writing /[A-Z]+/ into the attribute introduces literal slash characters; it does not declare a JavaScript regular expression literal there.
Escape literal punctuation inside character classes
Under v mode, character classes support set operations. Literal punctuation that older expressions left unescaped may need a backslash. MDN lists (, ), [, {, }, /, -, and |, in addition to ] and \.
In the shelf example, \- means a literal hyphen. A range such as A-Z still uses the hyphen as an operator. Inspect each occurrence according to its purpose; do not insert escapes by mechanically replacing every hyphen in an existing expression.
Use a different requirement to see why Unicode awareness matters. This example allows 2–24 Unicode letters, without digits, spaces, or punctuation:
<label for="index-label">Index label</label>
<input id="index-label" name="indexLabel" type="text"
pattern="\p{Letter}{2,24}"
aria-describedby="index-rule">
<p id="index-rule">Optional. Use 2–24 letters without spaces.</p>
This expression is a technical demonstration, not a suitable rule for people's names. Names can contain spaces, apostrophes, combining marks, and other characters that this narrow rule rejects. Choose the allowed text from the field's real purpose.
Keep HTML escaping separate from JavaScript string escaping
In literal HTML, the first example contains one backslash before the hyphen. In an ordinary JavaScript string, write two backslashes to produce that same attribute value:
const shelf = document.querySelector('#shelf');
shelf.setAttribute('pattern', '[A-Za-z0-9\\-]{3,12}');
console.log(shelf.getAttribute('pattern'));
The logged result should be [A-Za-z0-9\-]{3,12}. A framework template, JSON configuration, or another serialization step can add another escaping layer. Inspect the resulting DOM attribute rather than relying only on the source file's appearance.
To check expression syntax separately in a current JavaScript environment:
const expression = shelf.getAttribute('pattern');
const wholeValue = new RegExp('^(?:' + expression + ')$', 'v');
console.log(wholeValue.test('AB-4'));
This diagnostic does not replace the input's native validation or server checks. It helps expose a syntax error that an unenforced browser attribute might otherwise hide.
Distinguish an optional blank value from a malformed value
With no required, a blank input can pass even when its pattern describes nonempty text. That is useful for the optional index label. Add required when blank is not an acceptable answer.
pattern applies to text, search, tel, URL, email, and password inputs. It does not make a number input enforce a custom digit layout. Email and URL inputs also retain their type checks, so typeMismatch and patternMismatch answer different questions. Use HTML input types to choose the underlying control before adding an expression.
For the catalog form, test the final DOM attribute with accepted, rejected, and blank values, then inspect the validity flags. Keep the rule visible next to the field. The cataloger should be able to fix a shelf code from that explanation without learning regular-expression syntax.