Finger-friendly numerical inputs with `inputmode`
Publikováno: 30.4.2018
Forms are often a nightmare on mobile. We can make the process as pain-free as possible by reacting to context. Input fields that expect numerical values should have a numerical UI. Bringing up a number keyboard on small screens is easy on most platforms — just use a <input type="number">
.
This big button numeric keyboard is finger-friendly and will help prevent users bouncing from your form in frustration. However, type="number"
isn’t appropriate for all numbers.
On …
The post Finger-friendly numerical inputs with `inputmode` appeared first on CSS-Tricks.
Forms are often a nightmare on mobile. We can make the process as pain-free as possible by reacting to context. Input fields that expect numerical values should have a numerical UI. Bringing up a number keyboard on small screens is easy on most platforms — just use a <input type="number">
.
This big button numeric keyboard is finger-friendly and will help prevent users bouncing from your form in frustration. However, type="number"
isn’t appropriate for all numbers.
On (most) larger screens, number inputs come with an incrementer/decrementer button. It’s a useful piece of UI we get for free by default. It does, however, make this kind of input totally inappropriate for a credit card number, for example.
The spec itself makes this clear.
The
type=number
state is not appropriate for input that happens to only consist of numbers but isn’t strictly speaking a number. For example, it would be inappropriate for credit card numbers or US postal codes. A simple way of determining whether to usetype=number
is to consider whether it would make sense for the input control to have a spinbox interface (e.g., with "up" and "down" arrows). Getting a credit card number wrong by 1 in the last digit isn’t a minor mistake, it’s as wrong as getting every digit incorrect. So it would not make sense for the user to select a credit card number using "up" and "down" buttons. When a spinbox interface is not appropriate,type=text
is probably the right choice (possibly with apattern
attribute).
It’s easy to hide the up and down buttons with CSS:
input[type="number"] {
-moz-appearance: textfield;
}
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
It’s important to note that this isn’t the only difference between a number and text input. You should definitely follow the spec on this point! Some older browsers will strip out leading zeros for number inputs which would be a big problem for US ZIP codes. The often-useful maxlength
attribute is ignored on number inputs.
yes yes yes! <input type=number> can finally die the fiery death it deserves!
— Monica Dinculescu (@notwaldorf) March 13, 2018
Why would anybody dislike such a useful input?
The answer comes down to validation and using the input for the wrong thing. The number input performs input sanitization by default. If a user enters anything that isn’t a valid number, the value will be equal to an empty string — regardless of what the user can see on the screen.
This input sanitization can trip developers up, and there’s no way to turn it off. If you want to allow input that isn’t a valid number, don’t use type="number"
.
var numberinput = document.querySelector('input[type="number"]')
numberinput.value // will be ""
This might not be what you would intuitively expect. However, if you follow the spec and only use the number input for what its designed for — actual numbers — this behavior is unproblematic.
Number Input Alternatives
iOS Solution: Use the `pattern` Attribute on a Text Input
On iOS devices, using the pattern
attribute with a value of [0-9]*
will bring up the numeric keypad. This only works with this exact pattern — you can’t allow any extra characters.
<label for="creditcard">credit card number:</label> <input pattern="[0-9]*" type="text" name="creditcard">
Bear in mind that an iPhone won’t let the user switch keyboard type when this keyboard is displayed. Make sure these are the only keys they need to fill in the input correctly.
If you want to bring up a keypad of large numeric keys on iOS, you need to use the pattern
attribute even on number inputs. Otherwise, you’ll get small and finger-friendly buttons:
A Better Solution: `inputmode`
inputmode
has been a WHATWG spec for a couple of years, and has finally been implemented by Chrome as of version 66:
This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.
Desktop
Chrome | Opera | Firefox | IE | Edge | Safari |
---|---|---|---|---|---|
66 | No | 20 | No | No | No |
Mobile / Tablet
iOS Safari | Opera Mobile | Opera Mini | Android | Android Chrome | Android Firefox |
---|---|---|---|---|---|
No | No | No | No | No | No |
For the widest support possible, it can be combined with the pattern
attribute for iOS:
<label for="creditcard">credit card number:</label> <input inputmode="numeric" pattern="[0-9]*" type="text" name="creditcard">
This gives developers full control of the mobile UI without any extra baggage. It makes the UI finger-friendly while being more versatile than the pattern
attribute as we can allow any characters we like. It controls one thing — and one thing only. inputmode
is a great solution for those cases when it's inappropriate to use type="number"
.
Some people would go further and ditch type="number"
altogether once inputmode
has better support. I’m not convinced that’s wise, but type="number"
can be problematic.
if (numberInput.validity.valueMissing) {
errorMessage.textContent = "field must not be empty"
}
If you want to explicitly warn of empty number inputs, you’ll need to use:
if (numberInput.validity.valueMissing && !numberInput.validity.badInput) {
errorMessage.textContent = "field must not be empty"
}
According to Google, users abandon purchases twice as often on mobile as compared to desktop. Sales on phones account for only one third of all completed online purchases. Clearly people don’t tolerate fumbling through badly designed forms and jabbing at tiny inputs. Data entry needs to be effortless. While browser support is currently low, we're only really waiting on mobile browsers. Desktop support is largely irrelevant. The input elements introduced by HTML5 are great, but they miss some edge cases. This can fill in some gaps.
The post Finger-friendly numerical inputs with `inputmode` appeared first on CSS-Tricks.