iPhone / iOS : Presenting HTML 5 Keyboard for Postal Codes

IosIphoneHtmlInputKeyboard

Ios Problem Overview


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.

Ios Solutions


Solution 1 - Ios

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

Solution 2 - Ios

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.

Solution 3 - Ios

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

Solution 4 - Ios

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.

Solution 5 - Ios

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

Solution 6 - Ios

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 :)

Solution 7 - Ios

You can use the native HTML API attribute called inputmode="numeric", inputmode="decimal". (This is the preferred way to implement it) You can read further about input mode at the MDN here

<input type="number" inputmode="numeric" />

Solution 8 - Ios

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?

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRyan McGearyView Question on Stackoverflow
Solution 1 - IosAaron GrayView Answer on Stackoverflow
Solution 2 - IosdavidelrizzoView Answer on Stackoverflow
Solution 3 - Iosseaside98View Answer on Stackoverflow
Solution 4 - IosMark TomlinView Answer on Stackoverflow
Solution 5 - IosdavidcondreyView Answer on Stackoverflow
Solution 6 - IosrintaroView Answer on Stackoverflow
Solution 7 - Iosavi siboniView Answer on Stackoverflow
Solution 8 - IosJeremiah JinnoView Answer on Stackoverflow