73

There are several tricks for displaying different keyboards on mobile devices for HTML 5 inputs (i.e. <input> tags).

For example, some are documented on Apple's website, Configuring the Keyboard for Web Views.

enter image description here enter image description here

These are great for usability, but when it comes to an input for for international postal codes (mostly numeric, but letters allowed), we're left with some poor options. Most people recommend using the pattern="\d*" trick to show the numeric keyboard, but that doesn't allow for letter input.

The type="number" input type shows the regular keyboard but shifted to the numeric layout:

enter image description here

This works well for iOS devices, but it makes Chrome think the input must be a number and even changes the input's behavior (up/down increment and decrement the value).

enter image description here

Is there any way to get iOS to default to the numeric layout, but still allow for alphanumeric input?

Basically, I want the iOS behavior for type="number" but I want the field to behave like a regular text field on desktop browsers. Is this possible?

UPDATE:

Sniffing the user-agent for iOS and using the type="number" input type is not an option. type="number" is not meant for string values (like postal codes), and it has other side effects (like stripping leading zeros, comma delimiters, etc) that make it less than ideal for postal codes.

Ryan McGeary
  • 221,847
  • 11
  • 90
  • 102
  • I don't have an answer for this question but I wondered whether the new feature of iOS 8 custom keyboards could help. A Postal Code optimised custom keyboard would be helpful here. The problem might be how to raise the keyboard from the WebView. – Faisal Memon Aug 25 '14 at 22:15
  • I think I finally found a solution that meets all your requirements. I've updated my answer from last year to, I think, something much better. http://stackoverflow.com/a/31619707/806956 – Aaron Gray Jun 02 '16 at 20:10
  • @AaronGray Thanks. It's close, but because it seems to disable alpha characters on iPhones, it is still an unfinished problem. – Ryan McGeary Jun 06 '16 at 15:35
  • Ahh, I gotcha. :-) – Aaron Gray Jun 07 '16 at 00:11

7 Answers7

42

Will this work?

HTML:

<input type="tel" pattern="[0-9]*" novalidate>

This should give you the nice numeric keyboard on Android/iOS phone browsers, disable browser form validation on desktop browsers, not show any arrow spinners, allows leading zeros, and allows commas and letters on desktop browsers, as well as on iPad.

Android / iOS phones:

enter image description here

Desktop:

enter image description here

iPad:

enter image description here

Aaron Gray
  • 9,835
  • 6
  • 49
  • 57
  • This does seem to be the best option available, however this still doesn't fully conform with the US standard as the keyboard doesn't offer the dash character which is required for the Zip+4 system. That said, the Zip+4 isn't required or used heavily... https://en.wikipedia.org/wiki/ZIP_Code – PromInc Oct 07 '16 at 13:52
  • 1
    I really liked this as an reasonably all-purpose solution and used this myself. One caveat is that novalidate is formally only a supported attribute for
    s and not fields. Some browsers do support them on the input level - I didn't check comprehensively. The simplest alternative is to "novalidate" the entire form - although of course that may have unwelcome side effects.
    – DRosenfeld Jan 23 '17 at 13:34
11

Browsers currently have no proper way of representing numeric codes like postcodes and credit card numbers. The best solution is to use type='tel' which will give you a number keypad and ability to add any character on desktop.

Type text and pattern='\d*' will give you a number keypad but only on iOS.

There is an HTML5.1 proposal for an attribute called inputmode which would allow you to specify keypad regardless of type. However not is not currently supported by any browser.

I would also recommend having a look at the Webshim polyfill library which has a polyfill method for these types of inputs.

adam0101
  • 23,476
  • 18
  • 75
  • 147
davidelrizzo
  • 615
  • 7
  • 13
  • 1
    `pattern='/d'` did not work for me but `pattern='[0-9]*'` did. Thanks for the tip in any case – Miguel Guardo Feb 24 '17 at 03:52
  • 4
    That should say `pattern="\d*"` – tvanc Sep 27 '17 at 17:00
  • Speaking about inputmode..can i put the type="text" and the inputmode="numeric" on the same input field for credit card number as the following: or that will be not semantic or even may cause a problem? – Dani Mousa Feb 13 '20 at 20:30
10

A quick google search found this Stackoverflow question.

HTML

<input type="text">

Javascript

$('input[type="text"]').on('touchstart', function() {
   $(this).attr('type', 'number');
});

$('input[type="text"]').on('keydown blur', function() {
   $(this).attr('type', 'text');
});

The input type is switched before the form can be validated, showing the correct keyboard without messing up the value. If you only want it to run on iOS, you will probably have to use the user agent.

Stackoverflow on detecting iOS

Community
  • 1
  • 1
seaside98
  • 109
  • 1
  • 3
  • 11
    This is absolutely disgusting, but also the best solution to this problem I was able to find. I need a shower. – ca_peterson Aug 11 '15 at 23:24
  • 1
    This works, but it also clears the form every time you click in the box. With a few modifications this could potentially be the best answer. – cameronroytaylor Aug 08 '16 at 17:57
6

An update to this question in iOS 11. You can get the number keypad by simply adding the pattern attribute (pattern="[0-9]*") to any input with a number type.

The following works as expected.

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

This also works.

<input type="number" pattern="\d*">

@davidelrizzo posted part of the answer, but the comments from @Miguel Guardo and @turibe give a fuller picture but are easy to miss.

Mark Tomlin
  • 7,684
  • 8
  • 51
  • 68
5

This will make the numerical side of the ios keyboard display by default and maintains the ability to switch to the alphabetical side. When the html input type changes, the device changes the keyboard to match the appropriate type.

(function ($) {
    var control = $('#test2');
    var field = $('#test1');

    control.bind('click', function () {
        if (control.is(':checked')) {
            field.attr('type', 'text');
        } else {
            field.attr('type', 'number');
        }
    })
}(jQuery));

<input type="number" id="test1" value="123" />
<input id="test2" type="checkbox" />Change

enter image description here


alternate demo: http://jsfiddle.net/davidcondrey/dbg1L0c0/3/embedded/result/

If you want the large numerical format keyboard (the telephone style) you can adjust the code accordingly and it still works:

(function ($) {
    var control = $('#test2');
    var field = $('#test1');

    control.bind('click', function () {
        if (control.is(':checked')) {
            field.attr('type', 'text');
        } else {
            field.attr('type', 'tel');
        }
    })
}(jQuery));

<input type="tel" id="test1" value="a" />
<input id="test2" type="checkbox" />Change

enter image description here

davidcondrey
  • 29,530
  • 14
  • 105
  • 129
1

Try this:

<input type="text" name="postalcode" class="js-postal">
<script src="https://code.jquery.com/jquery-2.1.1.js" type="text/javascript"></script>
<script type="text/javascript">
$(function() {
  if('ontouchstart' in window) { // ensure we are in touch device.

    $('input.js-postal').on('focus', function() {
      var $this = $(this);

      // memorize current value because...
      var val = $this.val(); 
      // this may cause reset value.
      $this.attr('type', 'number'); 

      setTimeout(function() {
        // Asynchronously restore 'type' and value
        $this.attr('type', 'text');
        $this.val(val);
      }, 0);
    });
  }
});
</script>

I know this is very hackish way, but this apparently works.
I haven't tested on Android devices though.

Note this may causes a little noticeable glitches when $this.attr('type', 'number') because this reset the value when input has non numerical characters.

Basic ideas are stolen from this answer :)

Community
  • 1
  • 1
rintaro
  • 48,979
  • 13
  • 123
  • 135
-1

Why not check the header of the HTTP request (user agent), and serve up the numeric layout to the iOS devices, while serving up the alphanumeric layout to the rest?

  • 4
    Sniffing the user-agent for iOS and using the `type="number"` input type is not a great option. `type="number"` is not meant for string values (like postal codes), and it has other side effects (like stripping leading zeros, comma delimiters, etc) that make it less than ideal for postal codes. Not to mention, sniffing user-agents makes for a brittle implementation. – Ryan McGeary Aug 26 '14 at 03:38