Cracking the Code For a Numeric Keyboard

Rob Tarr is on a mission. Destination: proper numeric keyboard.

Recently, I was asked by a client to make modifications to a form in order to make it more mobile friendly. A simple request really. They wanted the numeric keyboard to display on mobile devices when a user tapped on fields requiring numbers (i.e. phone, date, zip code).

This seems like it should be a simple task, right? With the new HTML5 input types, I can set the input type for phone to “tel,” date to “date,” and zip to... "number?" 

Well, that almost works. <input type="number"> will display the number keyboard, but it also throws another wrinkle into the situation. Any number entered with more than three digits has a comma added to it (depending on internationalization settings). So when I enter a zip code of 45402, the resulting text in the field is 45,402. At least, this is the case for iOS.

So began my quest. I was out to find an input that made sense and provided a numeric keyboard for mobile devices without inserting a comma into the value.

Check out the test page to see my results so far. Also, please feel free to fork the gist and add your own tests. Final thoughts below the gist:

<!doctype html>
<html>
<head>
<title>Number Test</title>
<style>
tr {
background: #ddd;
}
tr:nth-child(odd) {
background: #ccc;
}
td {
border: 1px solid #bbb;
}
</style>
</head>
<body>
<table>
<thead>
<tr>
<th>Input</th>
<th>Chrome 16 (Mac)</th>
<th>Firefox 8 (Mac)</th>
<th colspan="2">iOS 5</th>
<th colspan="2">Kindle Fire</th>
</tr>
<tr>
<th></th>
<th>Comma</th>
<th>Comma</th>
<th>Comma</th>
<th>Keyboard</th>
<th>Comma</th>
<th>Keyboard</th>
</tr>
<tbody>
<tr>
<td>
<input type="number" value="45402">
<pre>&lt;input type="number" value="45402"></pre>
</td>
<td>no</td><td>no</td>
<td>yes</td><td>number</td>
<td>no</td><td>keypad</td>
</tr>
<tr>
<td>
<input type="number" value="45402">
<pre>&lt;input type="number" value="45402"></pre>
</td>
<td>no</td><td>no</td>
<td>yes</td><td>number</td>
<td>no</td><td>keypad</td>
</tr>
<tr>
<td>
<input type="number" value="45402" pattern="[0-9]*">
<pre>&lt;input type="number" value="45402" pattern="[0-9]*"></pre>
</td>
<td>no</td><td>no</td>
<td>yes</td><td>keypad</td>
<td>no</td><td>keypad</td>
</tr>
<tr>
<td>
<input type="number" value="45402" pattern="[0-9]{5}">
<pre>&lt;input type="number" value="45402" pattern="[0-9]{5}"></pre>
</td>
<td>no</td><td>no</td>
<td>yes</td><td>number</td>
<td>no</td><td>keypad</td>
</tr>
<tr>
<td>
<input type="number" value="45402" name="zip">
<pre>&lt;input type="number" value="45402" name="zip"></pre>
</td>
<td>no</td><td>no</td>
<td>yes</td><td>number</td>
<td>no</td><td>keypad</td>
</tr>
<tr>
<td>
<input type="text" value="45402" name="zip">
<pre>&lt;input type="text" value="45402" name="zip"></pre>
</td>
<td>no</td><td>no</td>
<td>no</td><td>text</td>
<td>no</td><td>text</td>
</tr>
<tr>
<td>
<input type="number" value="45402" name="phone">
<pre>&lt;input type="number" value="45402" name="phone"></pre>
</td>
<td>no</td><td>no</td>
<td>yes</td><td>number</td>
<td>no</td><td>keypad</td>
</tr>
<tr>
<td>
<input type="text" value="45402" name="phone">
<pre>&lt;input type="text" value="45402" name="phone"></pre>
</td>
<td>no</td><td>no</td>
<td>no</td><td>text</td>
<td>no</td><td>text</td>
</tr>
<tr>
<td>
<input type="tel" value="45402">
<pre>&lt;input type="tel" value="45402"></pre>
</td>
<td>no</td><td>no</td>
<td>no</td><td>keypad</td>
<td>no</td><td>keypad</td>
</tr>
<tr>
<td>
<input type="text" value="45402">
<pre>&lt;input type="text" value="45402"></pre>
</td>
<td>no</td><td>no</td>
<td>no</td><td>text</td>
<td>no</td><td>text</td>
</tr>
<tr>
<td>
<input type="text" value="45402" pattern="[0-9]*">
<pre>&lt;input type="text" value="45402" pattern="[0-9]*"></pre>
</td>
<td>no</td><td>no</td>
<td>no</td><td>keypad</td>
<td>no</td><td>text</td>
</tr>
<tr>
<td>
<input type="text" value="45402" pattern="[0-9]{5}">
<pre>&lt;input type="text" value="45402" pattern="[0-9]{5}"></pre>
</td>
<td>no</td><td>no</td>
<td>no</td><td>text</td>
<td>no</td><td>text</td>
</tr>
<tr>
<td>
<input type="text" value="45402" pattern="[0-9]{5}(-[0-9]{4})*">
<pre>&lt;input type="text" value="45402" pattern="[0-9]{5}(-[0-9]{4})*"></pre>
</td>
<td>no</td><td></td>
<td>no</td><td>text</td>
<td>no</td><td>text</td>
</tr>
<tr>
<td>
<input type="pc" value="45402">
<pre>&lt;input type="pc" value="45402"></pre>
</td>
<td>no</td><td></td>
<td>no</td><td>text</td>
<td>no</td><td>text</td>
</tr>
<tr>
<td>
<input type="date" value="45402">
<pre>&lt;input type="date" value="45402"></pre>
</td>
<td>no</td><td></td>
<td>--</td><td>Date dropdown</td>
<td>no</td><td>text</td>
</tr>
</tbody>
</table>
</body>
view raw inputs.html hosted with ❤ by GitHub

The only input type that really gets me what I want is <input type="tel">. However, it feels wrong to use this for non-telephone numbers. I just can’t bring myself to do it. This leaves me with <input type="text" pattern="[0-9]*">, which provides zip codes that look right and numeric keyboards in iOS. Sorry, Android users – we’ll hopefully figure out something better that includes you soon.

If you have other suggestions, I’m open. Feel free to add to the gist if you have other input ideas.

Also, check out what @brad_frost wrote on this topic just the other day.