The phone number input field in HTML
A text field that takes the number the way people write it, lets the browser fill it in, and leaves the reading to the server. One field for the number, one country for numbers typed without their code, nothing reformatted while they type.
The field
<label for="phone">Phone number</label>
<input id="phone" name="phone" type="tel" autocomplete="tel"
required maxlength="40" aria-describedby="phone-hint">
<p id="phone-hint">With its country code, or as you dial it in the country below.</p>
<label for="phone-region">Country</label>
<select id="phone-region" name="phone_region">
<option value="GB" selected>United Kingdom (+44)</option>
<option value="US">United States (+1)</option>
<!-- … every country you serve, the person's own selected -->
</select>type="tel"brings up the phone keypad on touch screens and keeps the text exactly as typed. It validates nothing, which is right: no browser knows the plans.autocomplete="tel"lets the browser fill in the person's saved number, in full international form. For a number split over several fields the standard hastel-country-code,tel-nationaland more; one field avoids the split.- One field, not three. Country code, area code and subscriber boxes assume one plan's shape; area codes run from none to five digits, and a pasted number lands in the first box.
- The country is only for numbers typed without a country code:
07400 123456needs it,+44 7400 123456does not. Default it to the person's country and pass it toparseas the default region. - No formatting as they type. Inserted spaces and brackets move the cursor, fight a paste and guess wrong for plans you do not know. Read the number when the form is sent, and show it formatted after.
- Validate on the server with the plans: the guides'
parsereturns the E.164 form, or nothing — then say which country you read it in, so the person sees why.
What the browser does with a phone number
Each row is a field, a number typed into it key by key, and what the browser reports back, in Chromium. type="number" is for quantities; a phone number in it loses what makes it one.
| Field | Typed | Read back | What it means |
|---|---|---|---|
| <input type="tel"> | +44 (0)7400 123456 | value = +44 (0)7400 123456 | keeps the number exactly as typed |
| <input type="tel"> | call me | valid = true | checks nothing: validation is yours |
| <input type="number"> | 07400 123456 | value = 07400123456 | refuses the spaces as they are typed |
| <input type="number"> | +447400123456 | value = 447400123456 | refuses the plus: +44 becomes 44, the start of a national number |
| <input type="number"> | 07400123456 | valueAsNumber = 7400123456 | turns digits into a quantity: the trunk 0 is gone |
| <input type="tel" pattern="[0-9]{11}"> | 074001234567 | patternMismatch = true | anchors the pattern: it must match the whole value |
| <input type="tel" pattern="[0-9 ()+-]+"> | call me | patternMismatch = false | ignores a pattern that is not valid with the v flag: an unescaped ( ) or - in a class |
| <input type="tel" pattern="[0-9 \(\)+\-]+"> | call me | patternMismatch = true | applies the same pattern escaped |
| <input type="tel" pattern="[0-9 \(\)+\-]+"> | +44 (0)7400 123456 | patternMismatch = false | and lets a written number through |
The pattern attribute is compiled as a JavaScript regular expression with the v flag and matched against the whole value. Under that flag, (, ), -, [,], {, }, /, \ and | must be escaped inside a character class. A pattern that does not compile is not an error the page shows: the field simply has no pattern. A pattern can at most check characters and length; whether the number exists in its plan is the server's question.
Sources: HTML Standard: the autocomplete attribute (tel, tel-country-code, tel-national…) (WHATWG); HTML Standard: the pattern attribute (WHATWG). The table is run in a browser before it is published.