Skip to content

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 has tel-country-code, tel-national and 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 123456 needs it, +44 7400 123456 does not. Default it to the person's country and pass it to parse as 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' parse returns 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.

FieldTypedRead backWhat it means
<input type="tel">+44 (0)7400 123456value = +44 (0)7400 123456keeps the number exactly as typed
<input type="tel">call mevalid = truechecks nothing: validation is yours
<input type="number">07400 123456value = 07400123456refuses the spaces as they are typed
<input type="number">+447400123456value = 447400123456refuses the plus: +44 becomes 44, the start of a national number
<input type="number">07400123456valueAsNumber = 7400123456turns digits into a quantity: the trunk 0 is gone
<input type="tel" pattern="[0-9]{11}">074001234567patternMismatch = trueanchors the pattern: it must match the whole value
<input type="tel" pattern="[0-9 ()+-]+">call mepatternMismatch = falseignores a pattern that is not valid with the v flag: an unescaped ( ) or - in a class
<input type="tel" pattern="[0-9 \(\)+\-]+">call mepatternMismatch = trueapplies the same pattern escaped
<input type="tel" pattern="[0-9 \(\)+\-]+">+44 (0)7400 123456patternMismatch = falseand 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.