Better Numerical Inputs for Mobile Forms

usable numeric inputs in iOS

My colleagues in Chicago just launched a great responsively-designed greygoose.com, and Jason Grigsby and I were wondering how they brought up the user-friendlier telephone keypad in iOS instead of the ok-but-not-great number keypad. The team dynamically set the input type to tel with Javascript, but we were wondering if there would be a better way.

After some Twitter-talk with Grigsby and Chris Coyier, I set up a demo page to see if setting pattern="[0-9]* would make a difference. Thankfully it did.

So here’s the recommended format for numeric input types:

<input type="number" pattern="[0-9]*" />

Adding pattern="[0-9]*" triggers iOS to bring up the obese-finger-friendly keypad instead of the just-alright numeric keypad riddled with punctuation. Usability wins and the crowd goes wild.

By default iOS only triggers the number-only keypad on tel inputs, but this way the input type and the keypad don’t need to be bound. Semantics win and the crowd rises to their feet in jubilation.

Also worth noting the Kindle Fire pulls up a friendlier keypad regardless of whether pattern="[0-9]* is set:

Number & Tel inputs on Amazon Kindle

Number & Tel inputs on Amazon Kindle

Big thanks to Björn Rixman, Chris and Jason for working through this!

Related Resources:

Update

There are a few things that people pointed out in the comments or in other posts regarding numeric input types:

  • Not all inputs that contain numbers (credit cards, SS#, etc) should have an input type of number. They are best served up as text inputs, which are still free to use the pattern attribute to pull up the tel keypad on supported devices.
  • Submitting input type="number" inserts a thousands separator in iOS, which can screw up form submission.
  • For all the talk about semantics, it really boils down to creating a user experience, which means that dynamically setting the input type to tel with JS is a decent stopgap.

Some fine people have written about these issues in more detail:

14 Comments

  1. Matt Menzer

    Nice work, all.

  2. I just did some work on this last week as well. Turns out some people get a “thousand separator” in the input field when using this method on iOS. Nothing is submitted to the server, but it is kind of confusing when you are typing in stuff like for instance a customer id, and not a price. I do not know of any way to removing it, but I don’t think “tel” has this behavior.

    PS. This works on Android as well.

    • Thanks for the heads up! I tried to replicate the behavior in iOS4 and iOS5 using this test page but wasn’t able to get the returned value to produce a thousands separator. Perhaps setting the min, max and step attributes affects it?

      I suppose it’s a good idea for those numbers to be sanitized anyways once the form is submitted, especially with things like customer IDs.

      So this means it’s still entirely safe for use for numbers less than 1000, which could be implemented like by adding a max attribute: max="999".

      Ultimately this little issue shows that ain’t nuthin’ easy in this bitch.</elegence>

  3. Hi Brad,

    I ended up using the pattern you show to trigger the iOS numeric keyboard input, but with an input type of text field instead of number. This was precisely for the issue that @anders mentioned: the thousands separator was appearing when the input type was number, and this was confusing people a bit. This would happen, for example, when switching to the next input field.

    Also, I wanted to allow other input characters, such as space and dash, because users want to enter their credit card numbers in stanzas like that. So getting the iOS numeric keyboard, but making it easy to enter selected separators, while also avoiding the thousands separator issue was a win for me.

    I could use the number type for the cvv field, but sometimes that’s 4 digits, so the thousands separator issue returns. I didn’t try tel for that, which might be better in terms of fat fingering.

    Thanks for the experiment and suggestion.

    • Thanks for the insight, John! That’s very interesting about the behavior, especially switching in between fields. The input type=text is quite interesting from a semantics standpoint. Is something with dashes (SS# etc) a number or is a string primarily consisting of numbers? I would still say number is semantic, but the text input type seems to make sense too. And you can definitely justify it further with the iOS bug.

  4. Ron

    This is great; I had been changing the type to tel for IOS devices that support number and tel types, which was a real ugly workaround.

    Interestingly, the spec itself indicates that the pattern attribute is technically invalid for the number type. http://dev.w3.org/html5/spec/Overview.html#number-state-type-number

    (Also invalid is the “placeholder” type, which is another one I don’t understand)

  5. We went around in circles with this recently too. We have forms that need to accept telephone, fax, credit cards, #SS, etc.

    Using “number” did add the thousand separator. My digging found that the W3C doesn’t look at numbers the way we did. They keep referencing “floating point numbers” which are not your usual strings like a credit card number as far as I can see.

    http://dev.w3.org/html5/spec/Overview.html#valid-floating-point-number

    For the time being I recommend using type=”text” for HTML5 form elements that handled numbers, but did not have a specific HTML5 type associated with them, like type=”tel”.

    I’ve got to think there is a way to handle these, much like adding a single apostrophe before a number string in an Excel cell does.

    I live in hope 🙂

  6. I have just used input type tel on a project to tak bike rental reservations. I was (please don’t stone me) more concerned about the user experience than the semantics. You can see the outcome at http://www.youngsbicycleshop.com/bicycle-reservations.html on a mobile device. It was the first mobile optimized shopping cart for me.

  7. Gareth

    Remember that credit card data (and the like) isn’t numeric data. It’s string data that just happens to only have numeric characters. You can’t add them or multiply them.

    If you think like this then you’ll also realise why the bank sort code “05 25 55” isn’t the same as “52555” – although if the data was numeric it *would* be.

  8. Rob

    Now if only we could get a keyboard that uses pattern but also includes a decimal point!!!!

  9. “For all the talk about semantics, it really boils down to creating a user experience, which means that dynamically setting the input type to tel with JS is a decent stopgap.”

    Sorry, but you can’t dynamically set the input type with JS in just about any modern browser. It’s a security concern – the input type attribute cannot be changed with JavaScript.

    You should do some research or test your assumptions before you post them.

  10. Another top tip: use inputmode=”numeric” and it will bring up the number keypad on Firefox for Android. I currently use this on my webforms and it works great.

  11. @John Keith

    “Also, I wanted to allow other input characters, such as space and dash, because users want to enter their credit card numbers in stanzas like that. So getting the iOS numeric keyboard, but making it easy to enter selected separators, while also avoiding the thousands separator issue was a win for me.”

    John, just wondering how you got the other input types like space and dash to appear?

    I’m using The ‘fat finger’ keypad this produces on iOS6 is great. I just need to add a decimal point.

    I notice that http://greygoose.com has some other input types like #. Not sure how they achieved this.

Comments are closed for this post. If you've got something to add, feel free to reach out on Twitter.