Docs LogoDocs

Input Patterns - Regex Validation for Forms

Documentation for Input Patterns - Regex Validation for Forms.

Input Patterns - Regex Validation for Forms

What is the Pattern Attribute?

The pattern attribute specifies a regular expression that the input's value must match for validation.

Definition: The pattern attribute provides client-side validation using regular expressions (regex). When a form is submitted, the browser checks if the input value matches the pattern. If not, the form won't submit and shows a validation message.

<input type="text" pattern="[A-Za-z]{3,}" title="At least 3 letters required" />

How Pattern Works

<input
  type="text"
  pattern="[0-9]{5}"           <!-- Regex pattern -->
  title="Enter 5-digit ZIP"    <!-- Custom error message -->
  required                     <!-- Makes empty invalid too -->
>
ComponentPurpose
patternRegex the value must match
titleTooltip + part of validation message
requiredPrevents empty values (pattern allows empty by default)

Pattern vs Input Type

Input TypeBuilt-in ValidationAdd Pattern For
emailValid email formatSpecific domain requirements
urlValid URL formatSpecific protocol/domain
telNone (just numeric keyboard)Phone format validation
numberNumeric with min/maxSpecific number formats
textNoneAny format validation

Regex Basics for Patterns

Character Classes

PatternMeaningExample Match
[abc]Any of a, b, or c"a", "b", "c"
[a-z]Any lowercase letter"m", "z"
[A-Z]Any uppercase letter"A", "M"
[0-9]Any digit"5", "9"
[a-zA-Z]Any letter"a", "Z"
[^abc]NOT a, b, or c"d", "1"
.Any character except newline"x", "1", "@"

Quantifiers

PatternMeaningExample
*0 or morea* → "", "aaa"
+1 or morea+ → "a", "aaa"
?0 or 1a? → "", "a"
{n}Exactly na{3} → "aaa"
{n,}n or morea{2,} → "aa", "aaaa"
{n,m}Between n and ma{2,4} → "aa", "aaa"

Anchors and Groups

| Pattern | Meaning | | -------- | ------------------------------------- | ------ | | ^ | Start of string (implicit in pattern) | | $ | End of string (implicit in pattern) | | (abc) | Group | | (a | b) | a OR b | | (?:ab) | Non-capturing group |

Escape Characters

PatternMeaning
\dAny digit [0-9]
\wWord char [a-zA-Z0-9_]
\sWhitespace
\.Literal dot
\+Literal plus
\\Literal backslash

Common Input Patterns

Name Patterns

<!-- Letters only, 2-50 characters -->
<input
  type="text"
  pattern="[A-Za-z]{2,50}"
  title="2-50 letters only"
  required
/>

<!-- Letters with spaces (full name) -->
<input
  type="text"
  pattern="[A-Za-z\s]{2,100}"
  title="Letters and spaces only"
  required
/>

<!-- Name with international characters -->
<input
  type="text"
  pattern="[\p{L}\s'-]{2,100}"
  title="Valid name required"
  required
/>

Username Patterns

<!-- Alphanumeric, 3-20 characters -->
<input
  type="text"
  pattern="[A-Za-z0-9]{3,20}"
  title="3-20 alphanumeric characters"
  required
/>

<!-- Alphanumeric with underscore, starting with letter -->
<input
  type="text"
  pattern="[A-Za-z][A-Za-z0-9_]{2,19}"
  title="Start with letter, 3-20 chars, letters/numbers/underscore"
  required
/>

<!-- No spaces, lowercase only -->
<input
  type="text"
  pattern="[a-z0-9_]{3,15}"
  title="Lowercase letters, numbers, underscore. 3-15 chars"
  required
/>

Password Patterns

<!-- Minimum 8 characters -->
<input type="password" pattern=".{8,}" title="At least 8 characters" required />

<!-- At least one uppercase, lowercase, number -->
<input
  type="password"
  pattern="(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}"
  title="8+ chars with uppercase, lowercase, and number"
  required
/>

<!-- Strong password with special char -->
<input
  type="password"
  pattern="(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&]).{8,}"
  title="8+ chars: uppercase, lowercase, number, special char"
  required
/>

Email Patterns

<!-- Standard email (browser has built-in) -->
<input type="email" required />

<!-- Specific domain only -->
<input
  type="email"
  pattern="[a-z0-9._%+-]+@company\.com"
  title="Must be a company.com email"
  required
/>

<!-- Multiple allowed domains -->
<input
  type="email"
  pattern="[a-z0-9._%+-]+@(gmail|yahoo|outlook)\.com"
  title="Gmail, Yahoo, or Outlook only"
  required
/>

<!-- No disposable email domains -->
<input
  type="email"
  pattern="[a-z0-9._%+-]+@(?!(tempmail|throwaway)\.com)[a-z0-9.-]+\.[a-z]{2,}"
  title="No disposable emails"
  required
/>

Phone Number Patterns

<!-- US phone: (123) 456-7890 or 123-456-7890 -->
<input
  type="tel"
  pattern="\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}"
  title="Format: (123) 456-7890 or 123-456-7890"
  required
/>

<!-- US phone with optional country code -->
<input
  type="tel"
  pattern="(\+1)?[-.\s]?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}"
  title="US phone number"
  required
/>

<!-- International phone -->
<input
  type="tel"
  pattern="\+?[0-9]{10,15}"
  title="10-15 digits, optional + prefix"
  required
/>

<!-- Indian phone: +91 or 10 digits -->
<input
  type="tel"
  pattern="(\+91[\s]?)?[6-9]\d{9}"
  title="Indian phone: 10 digits starting with 6-9"
  required
/>

Postal/ZIP Code Patterns

<!-- US ZIP code: 12345 or 12345-6789 -->
<input
  type="text"
  pattern="\d{5}(-\d{4})?"
  title="5 digit ZIP or ZIP+4 format"
  required
/>

<!-- Canadian postal code: A1A 1A1 -->
<input
  type="text"
  pattern="[A-Za-z]\d[A-Za-z][\s]?\d[A-Za-z]\d"
  title="Format: A1A 1A1"
  required
/>

<!-- UK postcode -->
<input
  type="text"
  pattern="[A-Z]{1,2}\d[A-Z\d]?\s?\d[A-Z]{2}"
  title="UK postcode format"
  required
/>

<!-- Indian PIN code: 6 digits -->
<input type="text" pattern="[1-9][0-9]{5}" title="6-digit PIN code" required />

Credit Card Patterns

<!-- Any card: 13-19 digits -->
<input
  type="text"
  pattern="\d{13,19}"
  title="13-19 digit card number"
  required
/>

<!-- With spaces/dashes: 1234 5678 9012 3456 -->
<input
  type="text"
  pattern="[\d\s-]{13,23}"
  title="Card number with optional spaces/dashes"
  required
/>

<!-- Visa: Starts with 4, 16 digits -->
<input
  type="text"
  pattern="4\d{15}"
  title="Visa card: 16 digits starting with 4"
  required
/>

<!-- Mastercard: Starts with 51-55 or 2221-2720 -->
<input
  type="text"
  pattern="(5[1-5]\d{14})|(2[2-7]\d{14})"
  title="Mastercard number"
  required
/>

<!-- CVV: 3-4 digits -->
<input type="text" pattern="\d{3,4}" title="3 or 4 digit CVV" required />

<!-- Expiry: MM/YY -->
<input
  type="text"
  pattern="(0[1-9]|1[0-2])\/\d{2}"
  title="Format: MM/YY"
  required
/>

Date Patterns

<!-- DD/MM/YYYY -->
<input
  type="text"
  pattern="(0[1-9]|[12][0-9]|3[01])/(0[1-9]|1[0-2])/\d{4}"
  title="Format: DD/MM/YYYY"
  required
/>

<!-- MM/DD/YYYY -->
<input
  type="text"
  pattern="(0[1-9]|1[0-2])/(0[1-9]|[12][0-9]|3[01])/\d{4}"
  title="Format: MM/DD/YYYY"
  required
/>

<!-- YYYY-MM-DD (ISO) -->
<input
  type="text"
  pattern="\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])"
  title="Format: YYYY-MM-DD"
  required
/>

URL Patterns

<!-- HTTPS only -->
<input
  type="url"
  pattern="https://.*"
  title="URL must start with https://"
  required
/>

<!-- Specific domain -->
<input
  type="url"
  pattern="https?://(www\.)?example\.com/.*"
  title="Must be an example.com URL"
  required
/>

Social Media Patterns

<!-- Twitter/X handle -->
<input
  type="text"
  pattern="@?[A-Za-z0-9_]{1,15}"
  title="Twitter handle (1-15 chars)"
  required
/>

<!-- Instagram username -->
<input
  type="text"
  pattern="[A-Za-z0-9_.]{1,30}"
  title="Instagram username (1-30 chars)"
  required
/>

ID Patterns

<!-- Social Security Number: 123-45-6789 -->
<input
  type="text"
  pattern="\d{3}-\d{2}-\d{4}"
  title="Format: 123-45-6789"
  required
/>

<!-- Aadhaar number (India): 12 digits -->
<input
  type="text"
  pattern="[2-9]\d{11}"
  title="12-digit Aadhaar number"
  required
/>

<!-- PAN card (India): ABCDE1234F -->
<input
  type="text"
  pattern="[A-Z]{5}[0-9]{4}[A-Z]"
  title="Format: ABCDE1234F"
  required
/>

Other Common Patterns

<!-- Alphanumeric code: ABC-123 -->
<input type="text" pattern="[A-Z]{3}-\d{3}" title="Format: ABC-123" required />

<!-- Hexadecimal color: #FF0000 -->
<input
  type="text"
  pattern="#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})"
  title="Hex color code"
  required
/>

<!-- Version number: 1.0.0 -->
<input type="text" pattern="\d+\.\d+\.\d+" title="Format: X.Y.Z" required />

<!-- IP Address (basic) -->
<input
  type="text"
  pattern="\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"
  title="IP address format"
  required
/>

<!-- Time 24h: HH:MM -->
<input
  type="text"
  pattern="([01]\d|2[0-3]):[0-5]\d"
  title="Format: HH:MM (24-hour)"
  required
/>

Pattern Reference Table

Use CasePattern
Letters only[A-Za-z]+
Numbers only[0-9]+ or \d+
Alphanumeric[A-Za-z0-9]+
No special chars[A-Za-z0-9\s]+
Min length 8.{8,}
Exact 5 digits\d{5}
US Phone\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}
US ZIP\d{5}(-\d{4})?
Email domain.*@domain\.com
Strong password(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}

Interview Questions & Answers

Q1: What is the HTML pattern attribute and when should you use it?

The pattern attribute specifies a JavaScript regular expression that an input's value must match for the form to submit. It provides client-side validation beyond what input types offer. Use it when you need specific formats like phone numbers on type="tel" (which has no built-in validation), custom password requirements, or restricting email to specific domains. Remember pattern allows empty values by default - add required to prevent that. Always provide the title attribute for helpful error messages.


Q2: Why doesn't pattern work without the required attribute for empty inputs?

By design, pattern validation only applies when there's a value to validate. An empty input passes pattern validation because there's nothing to match against. This allows optional fields with format requirements - if filled, it must match the pattern; if empty, it's valid. To make a field both required and pattern-matched, use both attributes: <input pattern="..." required>. This is intentional behavior following the HTML specification.


Q3: How do you create a pattern for password strength validation?

Use lookahead assertions to require multiple character types without enforcing order: (?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}. Each (?=.*X) checks that X exists somewhere. This pattern requires at least one lowercase ([a-z]), one uppercase ([A-Z]), one digit (\d), and minimum 8 characters (.{8,}). Add (?=.*[@$!%*?&]) for special characters. The final .{8,} actually matches the string after the lookaheads verify character presence.


Q4: What's the difference between \d and [0-9] in patterns?

Both match digits 0-9 in most cases and are essentially equivalent in HTML patterns. \d is shorter to type, while [0-9] is more explicit. Technically, \d might match other Unicode digits in some regex engines, but in HTML patterns (which use JavaScript regex), they're identical for ASCII digits. Use whichever is more readable for your team. In character classes like [0-9A-Z], the bracket notation may be clearer.


Q5: How should you validate international phone numbers with pattern?

International phone validation is complex because formats vary by country. A general pattern like \+?[0-9]{10,15} allows optional +, then 10-15 digits. For better UX, use type="tel" for proper mobile keyboards, accept multiple formats (spaces, dashes, parentheses): [\d\s()-+]{10,20}, and either use a library for proper validation or validate server-side. For country-specific validation, provide separate patterns or use JavaScript with a library like libphonenumber.


Q6: Why is the title attribute important with pattern?

The title attribute provides user feedback when pattern validation fails. Browsers append it to the default validation message like "Please match the requested format: [title]". Without it, users see a generic message and don't know what format is expected. Write clear, helpful titles: "Enter 10-digit phone number" rather than "Invalid format". The title also shows as a tooltip on hover. For better UX, also show format hints near the input.


Q7: How do you validate that a value starts with a specific prefix?

Use ^ (start anchor) in your pattern: ^PRE.* or just PRE.* (patterns implicitly anchor at start/end). For example, to require URLs starting with https: pattern="https://.*" on a URL input. For a product code starting with "ABC": pattern="ABC\d{4}". Remember that HTML patterns automatically anchor to both start and end, so ABC means "exactly ABC" not "contains ABC".


Q8: Can you validate patterns across multiple fields without JavaScript?

Pure HTML cannot validate relationships between fields (like password confirmation). The pattern attribute only validates the individual input's value against its pattern. For cross-field validation like matching passwords, confirming email, or checking that end date is after start date, you need JavaScript. You can use the Constraint Validation API: input.setCustomValidity("Passwords don't match"). HTML5 validation is per-field only.


Q9: What's the pattern for validating Indian phone numbers?

A pattern for Indian mobile numbers: pattern="(\+91[\s-]?)?[6-9]\d{9}". This allows optional +91 prefix, then requires the number to start with 6, 7, 8, or 9 (valid mobile prefixes), followed by exactly 9 more digits. For accepting landlines too, it gets complex due to varying STD codes. For robust validation, consider: pattern="(\+91[\s-]?)?[0-9]{10}" and validate the actual carrier/region server-side.


Q10: How do you escape special characters in patterns?

Regex special characters (^ $ . * + ? { } [ ] \ | ( )) need escaping with backslash when you want the literal character. For a literal dot: \., for literal plus: \+, for literal question mark: \?. Example: file extension pattern .*\.pdf$ matches anything ending in ".pdf". For literal backslash, use \\. In HTML attributes, you don't need to escape the backslash itself - write pattern=".*\.pdf" not pattern=".*\\.pdf".

Last updated on July 15, 2026

On this page