iPhone / iOS : Presenting HTML 5 Keyboard for Postal Codes
Asked Answered
V

9

79

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.

Vanmeter answered 21/8, 2014 at 11:27 Comment(4)
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.Hixson
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. https://mcmap.net/q/47584/-iphone-ios-presenting-html-5-keyboard-for-postal-codesConjugated
@AaronGray Thanks. It's close, but because it seems to disable alpha characters on iPhones, it is still an unfinished problem.Vanmeter
Ahh, I gotcha. :-)Conjugated
C
47

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

Conjugated answered 24/7, 2015 at 21:1 Comment(2)
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... en.wikipedia.org/wiki/ZIP_CodeBoise
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 <form>s and not <input> 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.Kingery
M
13

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.

Monomer answered 21/2, 2015 at 2:31 Comment(3)
pattern='/d' did not work for me but pattern='[0-9]*' did. Thanks for the tip in any caseNullify
That should say pattern="\d*"Cavan
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: <input type="text" inputmode="numeric"> or that will be not semantic or even may cause a problem?Paleobiology
H
11

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

Holpen answered 1/9, 2014 at 21:11 Comment(2)
This is absolutely disgusting, but also the best solution to this problem I was able to find. I need a shower.Glyconeogenesis
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.Downtrend
H
7

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.

Hokeypokey answered 6/11, 2017 at 4:55 Comment(2)
does it have letters under the numbers tho?Firepower
@Martian2049 Yes it does. It's a full DTMF keypad.Hokeypokey
M
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

Maury answered 1/9, 2014 at 4:53 Comment(0)
P
4

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" />
Pediatrics answered 17/5, 2022 at 6:27 Comment(0)
R
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 :)

Rooftree answered 28/8, 2014 at 8:51 Comment(0)
B
0

<input type="tel" inputmode="decimal">

Above has been working for me for several years. By working, I mean that on mobile devices, a numeric virtual keyboard is displayed when the input receives focus. On iOS devices, the keyboard allows users to enter numbers, decimals, and characters. My keyboard event handler inserts thousand separators, and there is no issue with passing validation, so I assume that users could also type in commas. Negative values can be entered, so hyphens are allowed, though I don't see a hyphen on the iOS keyboard.

Boche answered 4/8, 2022 at 20:51 Comment(0)
A
-2

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?

Arundinaceous answered 26/8, 2014 at 0:22 Comment(1)
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.Vanmeter

© 2022 - 2025 — McMap. All rights reserved.