LEARNING OBJECTIVES โต
- Understand why the WHATWG HTML standard deliberately does not enforce automatic regex validation on
<input type="tel">. - Differentiate between
type="tel",type="number", andinputmode="numeric". - Trigger the native numeric 10-key telephone dialpad on iOS and Android devices.
- Construct resilient validation patterns using the
patternattribute aligned with ITU-T E.164 standards. - Integrate granular telephone autocomplete tokens (
tel-country-code,tel-national,tel).
๐ The Mental Model & Story (Intuitive Foundation)
Imagine an international customs officer who speaks only English trying to validate telephone numbers written on immigration cards.
- A traveler from the United States writes:
(415) 555-0199 - A traveler from the United Kingdom writes:
020 7946 0919 - A traveler from France writes:
01.42.68.55.00 - A traveler from Germany writes:
+49 30 12345-67(with a dynamic 2-digit internal extension) - A traveler from Japan writes:
03-3581-2361
+-------------------------------------------------------------------------------+
| THE GLOBAL TELEPHONY CHALLENGE |
| |
| USA: (415) 555-0199 France: 01.42.68.55.00 |
| UK: 020 7946 0919 Germany: +49 (0) 30 12345-67 |
| Brazil: (11) 98765-4321 Japan: 03-3581-2361 |
| |
| Browser Verdict: "There is no single global regex that fits all countries! |
| I will provide the dialpad, but YOU define the pattern." |
+-------------------------------------------------------------------------------+
If the browser tried to enforce a single rigid syntax rule for phone numbers (like it does for emails), millions of legitimate users around the world would be locked out of submitting web forms.
For this reason, the WHATWG specification designed <input type="tel"> as a semantic and UX control, not a rigid syntactic gatekeeper. It unlocks the mobile telephone dialpad and assistive technology announcements, but leaves syntactic validation up to the developer via the pattern attribute and backend telephony libraries.
Technical Deep Dive & Specifications
The Spec Rule: Why type="tel" Does Not Validate by Default
Unlike type="email" or type="url", an <input type="tel"> with no pattern attribute will consider any text string validโeven "Call Mom!" or "N/A".
const telInput = document.querySelector('input[type="tel"]');
telInput.value = "random text string";
console.log(telInput.validity.valid); // true
console.log(telInput.validity.typeMismatch); // undefined / false (No typeMismatch for tel!)
To enforce formatting constraints, you must explicitly pair type="tel" with a regular expression via the pattern attribute.
The Fatal Trap: Never Use type="number" for Phone Numbers!
Junior developers often mistakenly use <input type="number"> because phone numbers consist primarily of digits. This causes severe engineering defects:
+-------------------------------------------------------------------------------+
| WHY type="number" BREAKS PHONE NUMBERS |
+-------------------------------------------------------------------------------+
| 1. STRIPS LEADING ZEROS: User types "0208123456" -> Browser sends "208123456"|
| 2. DISALLOWS CHARACTERS: Rejects "+", "(", ")", "-", and spaces entirely. |
| 3. INTRUSIVE UI: Renders unwanted up/down increment stepper arrows. |
| 4. SCROLL WHEEL BUG: Accidental mouse scroll mutates the phone digits. |
| 5. SCIENTIFIC NOTATION: Numbers exceeding 16 digits switch to "1.234e+16". |
+-------------------------------------------------------------------------------+
Rule of Thumb: If you cannot perform meaningful mathematical addition or subtraction on the value (e.g., phone numbers, credit cards, zip codes, social security numbers), never use type="number". Always use <input type="tel"> or <input type="text" inputmode="numeric">.
Mobile Keyboard Optimization: The 10-Key Dialpad
Setting type="tel" prompts mobile operating systems to replace the standard QWERTY keyboard with a high-efficiency numeric dialpad:
+-------------------------------------------------------------+
| [ 1 ] [ 2 ABC ] [ 3 DEF ] |
| [ 4 GHI ] [ 5 JKL ] [ 6 MNO ] |
| [ 7 PQRS ] [ 8 TUV ] [ 9 WXYZ ] |
| [ + * # ] [ 0 ] [ โซ ] |
+-------------------------------------------------------------+
Companion Autocomplete Tokens for Telephony
The HTML standard defines dedicated tokens for the autocomplete attribute to accelerate mobile checkout and registration flows:
| Autocomplete Token | Purpose & Scope | Example Injected Value |
|---|---|---|
autocomplete="tel" |
Full international phone number with country code. | +14155550199 |
autocomplete="tel-country-code" |
Country calling code only. | +1 or 1 |
autocomplete="tel-national" |
Full number without country code. | (415) 555-0199 |
autocomplete="tel-area-code" |
Area or regional routing code. | 415 |
autocomplete="tel-local" |
Subscriber number without area code. | 5550199 |
Standard Telephony Regex Patterns
1. Strict International Standard (ITU-T E.164)
The ITU-T E.164 recommendation formats international numbers as a leading + followed by up to 15 digits with no spaces or punctuation:
<input
type="tel"
name="e164_phone"
pattern="^\+[1-9]\d{1,14}$"
title="Please enter a valid international phone number in E.164 format (e.g., +14155550199)"
placeholder="+14155550199"
required
>
2. Flexible North American Numbering Plan (NANP / US & Canada)
Accepts standard formats: (555) 123-4567, 555-123-4567, 5551234567, or +1 555 123 4567:
<input
type="tel"
name="us_phone"
pattern="^(?:\+?1\s*(?:[.-]\s*)?)?(?:\(\s*([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9])\s*\)|([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9]))\s*(?:[.-]\s*)?([2-9]1[02-9]|[2-9][02-9]1|[2-9][02-9]{2})\s*(?:[.-]\s*)?([0-9]{4})$"
title="Please enter a 10-digit North American phone number (e.g. 555-123-4567)"
placeholder="(555) 123-4567"
>
Input Type vs Inputmode Matrix
| Use Case | Recommended Markup | Mobile Keyboard Result |
|---|---|---|
| Telephone Call / SMS Number | <input type="tel"> |
Phone dialpad (includes +, *, #). |
| Credit Card Number | <input type="text" inputmode="numeric"> |
Strict numeric digits 0-9 (no telephone symbols). |
| Numeric OTP / 2FA Code | <input type="text" inputmode="numeric" pattern="[0-9]{6}"> |
Strict numeric keypad with autofill support. |
| Monetary Price / Currency | <input type="text" inputmode="decimal"> |
Numbers 0-9 with locale decimal separator (. or ,). |
๐ป Interactive Code Playground
Starter Code
Line-by-Line Code Breakdown
- Lines 105โ113: The country selector uses
autocomplete="tel-country-code", allowing modern autofill engines to match and select the user's localized country calling code. - Lines 116โ126: The primary subscriber phone input uses
type="tel"andautocomplete="tel-national". It enforces a flexible regex pattern^[0-9\s\(\)\-\.]{7,15}$allowing national punctuation without locking the user into a single country's format. - Lines 131โ142: The backup phone input demonstrates a strict E.164 pattern (
^\+[1-9]\d{7,14}$). It requires a leading+symbol followed by the country code and digits with no spaces. - Lines 73โ80: CSS
:user-invalidautomatically highlights formatting mismatches without firing prematurely on initial render.
Expected Browser Render Output
+-------------------------------------------------------------+
| Security Verification |
| Link your mobile device for Two-Factor Authentication (2FA) |
| |
| Country & Primary Phone Number * |
| [ ๐บ๐ธ +1 (US/CA) v ] [ 415-555-0199 ] |
| We will transmit a 6-digit SMS verification token. |
| |
| Emergency International Backup (Optional) |
| [ +14155550199 ] |
| Must begin with '+' followed by country code and digits. |
| |
| [ Transmit Verification Code ] |
+-------------------------------------------------------------+๐๏ธ Hands-On Exercise
๐ฏ The Challenge: Global Checkout Phone Dispatcher
You are constructing the shipping information step for an international e-commerce checkout.
Requirements:
- Create a
formwithaction="/checkout/shipping"andmethod="POST". - Add an input for Recipient Phone Number with
id="recipient-phone". - The phone field must be strictly
required. - The field must display a telephone dialpad on mobile devices and enable autofill for the user's full telephone number.
- Create a
patternthat requires either:- A standard 10-digit format with optional dashes:
\d{3}-?\d{3}-?\d{4}, OR - An international format starting with
+:\+\d{10,14}.
- A standard 10-digit format with optional dashes:
- Provide a descriptive
titlethat guides the user on proper formatting.
๐ Starter Code Sandbox
โ ๏ธ Common Pitfalls
- Using
type="number"for Phone Inputs: As detailed above,type="number"will strip leading zeros (e.g., UK07946becomes7946), break international+prefixes, and cause accidental number increments via mouse scrolling. - Overly Restrictive Regex: Creating a pattern that requires strictly
(XXX) XXX-XXXXwill instantly reject users who typeXXX.XXX.XXXX,XXX-XXX-XXXX, or international users. Keep client-side patterns flexible and normalize data on your backend. - Assuming
type="tel"Will Automatically Reject Letters: Remember:type="tel"withoutpatterndoes not reject alphabetical letters or punctuation. Always provide apatternif non-numeric entries must be blocked before submission.
๐ก Pro Tips
- Server-Side Normalization with Google's
libphonenumber: Client-side HTML patterns should provide lightweight instant feedback. On the backend, run telephone inputs through Google's open-sourcelibphonenumberlibrary (available in Go, Python, Java, and Node.js) to parse, validate carrier validity, and format numbers into standardized E.164 strings. - Auto-Formatting Masks with Event Listeners: If your product design mandates formatted inputs (e.g. automatically typing parentheses
(as the user types), attach aninputevent listener in JavaScript to format the display while preserving the raw digits in a hidden form input or dataset attribute. - Pairing with SMS One-Time Passwords (
autocomplete="one-time-code"): When building verification screens, pair your SMS code input withautocomplete="one-time-code". On iOS and Android, incoming SMS codes will appear directly in the keyboard suggestion bar for instant one-tap completion.
๐ Key Takeaways
<input type="tel">is designed to trigger the mobile telephone dialpad and semantic accessibility hints, but does not enforce regex validation by default.- Never use
type="number"for telephone numbers; it strips leading zeros, disallows formatting symbols (+,-), and introduces mousewheel increment bugs. - Use the
patternattribute to enforce specific domestic formats or the global ITU-T E.164 standard (^\+[1-9]\d{1,14}$). - Leverage specialized
autocompletetokens (tel,tel-country-code,tel-national) to maximize mobile autofill conversion rates. - For non-telephone pure numeric codes (like OTPs or credit cards), prefer
<input type="text" inputmode="numeric">. - --