In summary the main issue is that, according to the spec, `<input type="number">` is only for numbers that are going to be parsed into a Javascript number. It has to make sense to increment, decrement or do other numerical operations on it. It's not to be used for strings or identifiers that just so happen to be numbers, e.g. credit card numbers. I'll admit this is slightly surprising to me but it does make a certain amount of sense.
The solution is to use `<input type=”text” inputmode=”numeric” pattern="[0-9]*">`.
One good reason for this is that for things like credit card numbers, a good interface will accept leading, trailing, or interior spaces. Sites that make me type in values in exactly their own weird format are an abomination.
Site A: Ah ah ah! You put a slash in your date! No soup for you!
Site B: Ah ah ah! You didn't put a slash in your date! No soup for you!
To put it more succinctly and without unnecessarily referring to JavaScript semantics, type="number" is for quantities, not mere strings of digits.
It's an unfortunate accident of the English language that both are commonly called ‘numbers’. We might not have had this confusion if some other language were the lingua franca of computing.
That's a good rule of thumb there :) More pedantically, credit card numbers _aren't_ numbers in the first place. They are identifiers that happen to use numerical digits. Same as phone numbers. Treating them as numbers at any point in a system is an error. My dream is this detail of the HTML spec forces people to rethink their schema design while they're at it.
I've come across this problem a number of times. The same applies in, for example, passing IDs across in JSON where I use strings if at all possible.
Even money amount are typically challenging to treat as numeric as often that drops them into a float when you shouldn't be processing money amounts as floats.
inputmode=”numeric” and inputmode=”decimal” have different quirks between Android and iOS. inputmode also acts differently on iPad and iPhone, and the keyboard shown varies from that for pattern=, and support for inputmode is missing from iOS11 (or iOS12?). Tread carefully!
Note that type="number" is particularly horrible on iOS because it allows typing non-numeric values and then input.value just returns zero. Instead you must check input.checkValidity(), and perhaps use the CSS :invalid pseudo-selector to show the user that their entry is not valid. You cannot read the actual invalid value AFAIK on iOS (although you could simulate it by looking at key events, if you ignore selection and cut/paste).
Data entry with HTML is one area where you really want a native app, and you can get severely burnt trying to use a WebView. I have wasted months dealing with a variety of quirks over the years trying to make time entry friendly in HTML: all solutions have terrible compromises, and different browsers act quite differently (and can have nasty bugs).
This is off-topic, but I really like the current GOV.UK (several years old now). I don't really have opinions on the visual stuff, but I find it really pleasant to use.
Filing my self-assessment tax return (only required because I run a side-business) is a fantastically straightforward experience. Step-by-step information entry, pre-filled with what they already know (e.g. main employer's salary), then they give you a number at the end which you pay by card.
Having done the paper version exactly once before moving over to doing them online, I feel grateful every time I see that distinctive custom font.
Fantastically straight forward? I strongly disagree. I've done the SA many times, and trying to find out your balance or payments list or anything useful is now a kafka-esque nightmare. Last time I knew they must owe me money but they didn't say at the end, and it took me about 15 minutes to find out how much, with no indication of when it would arrive. At the end of the SA they even had some sort of message saying make sure you pay what you owe, which turned out to be nothing. This is all complicated because you pay on account, paying the next year's tax 15 months before you submit your return (they guess your next tax bill based on the previous one, as you don't submit the return for 9 months after the end of the tax year, so you don't get in too much credit).
The new SA process is no different from the old one, with minor cosmetic enhancements, but they've made it almost impossible to get to the old account sections.
Notice how there's no login button. On a website that relies on logging in. Now search for "self assessment login" or "self assessment account" or "self-assessment balance".
See any login button? See anything resembling a login? last year you could still get to the old account screen after some hunting, but that's gone now. The new account screen is a mass of text with links sprinkled through out, where the old one was a compact menu.
Plus, when you finally do find your accounts, you can only see one year at a time, have to use a drop down to change year, the amounts you owed are on one page, they amounts you paid are on another, some of these figures are still provisional, and nothing adds up.
As for submitting your company accounts, what a joke that used to be when they re-did it. I knew exactly what type of account I needed to submit. But to get to that form, I think they had a labyrinth of 16 web pages, each just one question per page, that you had to answer while they unhelpfully tried to pick the form you needed for you. Get the wrong form? No way to go back to see what answer you got wrong, no way to fix it, you just had to start again. It meant I had to go through it 3 or 4 times before I finally got the right form.
Before they "renovated" it, you just picked the form you needed.
They even did a whole blog post about how great the one page per question concept was, which turned out to be utterly bullshit.
I've lost all faith in the gov.uk team, I feel they're trying too hard to be cool and "innovative". They have thrown out convention, and are often making poor UIs and user journeys because of it.
Similarly, here is your reminder than US Zip Codes aren't numbers, because many of us here in the Northeast have them start with a zero (or even two). So don't store them as integers, because Boston is 02108, not 2108.
Some are yet to get the memo. Not so long ago, I've seen a TypeScript course that demonstrated union types with an example of representing zip codes as either strings or numbers…
It's good to see UX design problems analyzed from a technical perspective. Designers working on the web should be proficient at understanding the medium on which they work, and look beyond generating static images to toss over the wall for implementation.
> However the inputmode attribute is now supported by all the mobile browsers we test in.
This isn't extensive, which might be a tad misleading if you don't double check. They test on Chrome & Samsung for Android, and iOS is only the one engine.
And those three browsers seem to be the only mobile browsers that have implemented it. (Well, Opera Mobile as well). [0]
Desktop support is also extremely spotty.
This seems like it might be leaping the gun on expecting this standard to pick up the slack.
Whilst they might feel the support is there for their particular audience after 2019, I wouldn't, and would suggest that you need to check your particular audience closely before following this advice for your own site. (Which is fairly generic advice, but appropriate.)
The article covers quite a few issues with type=number, including some pretty bad accessibility ones. On balance I think even if inputmode doesn't have 100% support, those users will simply get a normal keyboard, which isn't so bad. Disclaimer - I work on the team.
In this case, the fallback is still a plain-text field, into which the user should enter numbers. Perfectly usable, but without the keyboard hint, so it seems like a graceful fallback to me.
Using "numeric" types for strings that look like base 10 numbers is an incredibly common mistake. It's one of those mistakes that works 99% of the time, which means it can become deeply embedded in architectures. We've recently seen this problem when a database for the first time for a non-numeric system in its ids and downstream systems that converted that to an integer started to fail.
My rule of thumb is that if it doesn't make sense to do arithmetic on it then it's not a number, it's probably a string.
> We've recently seen this problem when a database for the first time for a non-numeric system in its ids and downstream systems that converted that to an integer started to fail.
I can add another anecdote to that list. In my case it was some code in a consuming system that expected u16 sized int which broke when the producing system increased to 32 bit sized int. I mean, no code change just the auto increment on the database finally exhausted 16 bits.
Tangentially, this is why my first thought when designing a new system is to use uuid/guid stored as a string in hyphenated hexadecimal. It prevents any downstream consumer from even attempting to store it as an int. I'm now wary of things that look like int but aren't actually integers since people will often mistakenly treat them as such.
They were using it to get a numeric entry pad on mobile devices because users preferred that. They knew the types weren't "numbers". Now that inputmode=”numeric” has better browser support they recommend that.
The Government Digital Service does all kinds of cool work around accessibility for both users using assistive technology and users who are less technically able. Interesting talk here from 2014 https://www.youtube.com/watch?v=CUkMCQR4TpY
I guess that, as a government, they are required to cater for people with accessibility issues (in this case: people who cannot type but need to dictate to enter text).
If you then cannot support the most popular dictating application, that’s not a good look.
This is another reminder that floating point numbers are just a hack that should never be used by default. We have enough CPU, memory and bandwidth that we are able to transmit/store exact representation of numeric user input, and convert it to float only when necessary, as designed by programmer.
Indeed. Just like 32-bit integers, having fixed size floats as the default representation of numbers with a decimal component is a bad holdover from days of limited hardware.
Let programmers use floats when they have the performance analysis to justify it. Before then, it's just another kind of premature optimisation - and high level languages should be avoiding it.
It would be cool if more languages had support for fixed-point fractional numbers. Rolling your own requires re-implementing display and multiplication code, which is a decent reason for people to just use floats instead.
<input type=number> for things that are like telephone numbers and not like quantities is such a common mistake. It can be hilarious when, for example, a login form uses such a field for a Swedish personal identity number. I just need to click the up arrow ~1.996×10¹¹ times!
Really interesting article, and as with everyone else I also really admire their commitment to accessible design.
One interesting this I noticed in this piece was the text (not quoted for reasons that will soon become clear):
Using <input type=”text” inputmode=”numeric” pattern="[0-9]*"> allows for a degree of separation between how the user enters data (“input mode”), what the browser expects the user input to contain (type equals number), and potentially how it tries to validate it.
Which has incorrectly used closing quotes and correctly used straight quotes in the same code section, and then proper opening and closing quotes in the text section. I wonder how that happened.
Without any pattern specified, the code you posted will accept emojis as input, it's not a good choice for a numeric only field. It's also intended for phone numbers...
Unless I'm missing something, the graceful degradation is the `pattern="[0-9]"`. Certainly `input type="text"` is about as "degradation friendly" as you can get in HTML land...
I'm no web-dev, but shouldn't these things be sanitized server-side? In which case, except for the mobile keypad issue, all these problems would solve themselves?
The point is that giving the user a number input is a bad user experience. For example, users don't need or want up and down spin buttons to enter a phone number. That's long before it gets to a server.
These recommendations are irrespective of server side sanitisation.
Server side sanitisation doesn’t address any of the accessibility concerns. Server side sanitisation doesn’t address the silent dropping of characters concern. Server side sanitisation doesn’t address the incrementing/decrementing the value accidentally concern.
That’s because the issues being discussed here are about creating a good UI that minimizes errors, and has little to do with sanitisation.
You always should validate server side but this is to make it easy to use and accessible for users, PayPal has a custom input type that looks fancy but for example the Delete key is not working for it(no idea if is accessible or if you can type in it via speech)
[+] [-] ChrisSD|6 years ago|reply
The solution is to use `<input type=”text” inputmode=”numeric” pattern="[0-9]*">`.
[+] [-] downerending|6 years ago|reply
Site A: Ah ah ah! You put a slash in your date! No soup for you!
Site B: Ah ah ah! You didn't put a slash in your date! No soup for you!
[+] [-] pwdisswordfish2|6 years ago|reply
It's an unfortunate accident of the English language that both are commonly called ‘numbers’. We might not have had this confusion if some other language were the lingua franca of computing.
[+] [-] dylan-m|6 years ago|reply
[+] [-] VBprogrammer|6 years ago|reply
Even money amount are typically challenging to treat as numeric as often that drops them into a float when you shouldn't be processing money amounts as floats.
[+] [-] robocat|6 years ago|reply
Note that type="number" is particularly horrible on iOS because it allows typing non-numeric values and then input.value just returns zero. Instead you must check input.checkValidity(), and perhaps use the CSS :invalid pseudo-selector to show the user that their entry is not valid. You cannot read the actual invalid value AFAIK on iOS (although you could simulate it by looking at key events, if you ignore selection and cut/paste).
Data entry with HTML is one area where you really want a native app, and you can get severely burnt trying to use a WebView. I have wasted months dealing with a variety of quirks over the years trying to make time entry friendly in HTML: all solutions have terrible compromises, and different browsers act quite differently (and can have nasty bugs).
[+] [-] gbersac|6 years ago|reply
[+] [-] neves|6 years ago|reply
We must allow they to automatically use this keypad without the confusing behavior of the <input type=number>
[+] [-] unknown|6 years ago|reply
[deleted]
[+] [-] signalsmith|6 years ago|reply
Filing my self-assessment tax return (only required because I run a side-business) is a fantastically straightforward experience. Step-by-step information entry, pre-filled with what they already know (e.g. main employer's salary), then they give you a number at the end which you pay by card.
Having done the paper version exactly once before moving over to doing them online, I feel grateful every time I see that distinctive custom font.
[+] [-] jackdeansmith|6 years ago|reply
[+] [-] mattmanser|6 years ago|reply
The new SA process is no different from the old one, with minor cosmetic enhancements, but they've made it almost impossible to get to the old account sections.
Notice how there's no login button. On a website that relies on logging in. Now search for "self assessment login" or "self assessment account" or "self-assessment balance".
See any login button? See anything resembling a login? last year you could still get to the old account screen after some hunting, but that's gone now. The new account screen is a mass of text with links sprinkled through out, where the old one was a compact menu.
Plus, when you finally do find your accounts, you can only see one year at a time, have to use a drop down to change year, the amounts you owed are on one page, they amounts you paid are on another, some of these figures are still provisional, and nothing adds up.
As for submitting your company accounts, what a joke that used to be when they re-did it. I knew exactly what type of account I needed to submit. But to get to that form, I think they had a labyrinth of 16 web pages, each just one question per page, that you had to answer while they unhelpfully tried to pick the form you needed for you. Get the wrong form? No way to go back to see what answer you got wrong, no way to fix it, you just had to start again. It meant I had to go through it 3 or 4 times before I finally got the right form.
Before they "renovated" it, you just picked the form you needed.
They even did a whole blog post about how great the one page per question concept was, which turned out to be utterly bullshit.
I've lost all faith in the gov.uk team, I feel they're trying too hard to be cool and "innovative". They have thrown out convention, and are often making poor UIs and user journeys because of it.
[+] [-] vitaliyf|6 years ago|reply
See https://en.wikipedia.org/wiki/List_of_ZIP_Code_prefixes
[+] [-] drstewart|6 years ago|reply
[+] [-] pwdisswordfish2|6 years ago|reply
[+] [-] alexrage|6 years ago|reply
[+] [-] shakna|6 years ago|reply
This isn't extensive, which might be a tad misleading if you don't double check. They test on Chrome & Samsung for Android, and iOS is only the one engine.
And those three browsers seem to be the only mobile browsers that have implemented it. (Well, Opera Mobile as well). [0]
Desktop support is also extremely spotty.
This seems like it might be leaping the gun on expecting this standard to pick up the slack.
Whilst they might feel the support is there for their particular audience after 2019, I wouldn't, and would suggest that you need to check your particular audience closely before following this advice for your own site. (Which is fairly generic advice, but appropriate.)
[0] https://caniuse.com/#feat=input-inputmode
[+] [-] joelanman|6 years ago|reply
[+] [-] signalsmith|6 years ago|reply
[+] [-] globular-toast|6 years ago|reply
My rule of thumb is that if it doesn't make sense to do arithmetic on it then it's not a number, it's probably a string.
[+] [-] reggieband|6 years ago|reply
I can add another anecdote to that list. In my case it was some code in a consuming system that expected u16 sized int which broke when the producing system increased to 32 bit sized int. I mean, no code change just the auto increment on the database finally exhausted 16 bits.
Tangentially, this is why my first thought when designing a new system is to use uuid/guid stored as a string in hyphenated hexadecimal. It prevents any downstream consumer from even attempting to store it as an int. I'm now wary of things that look like int but aren't actually integers since people will often mistakenly treat them as such.
[+] [-] markmark|6 years ago|reply
[+] [-] aglionby|6 years ago|reply
[+] [-] maxcbc|6 years ago|reply
[+] [-] gatvol|6 years ago|reply
[+] [-] leokennis|6 years ago|reply
If you then cannot support the most popular dictating application, that’s not a good look.
[+] [-] rini17|6 years ago|reply
[+] [-] ivanbakel|6 years ago|reply
Let programmers use floats when they have the performance analysis to justify it. Before then, it's just another kind of premature optimisation - and high level languages should be avoiding it.
[+] [-] rocqua|6 years ago|reply
[+] [-] TazeTSchnitzel|6 years ago|reply
[+] [-] OisinMoran|6 years ago|reply
One interesting this I noticed in this piece was the text (not quoted for reasons that will soon become clear):
Using <input type=”text” inputmode=”numeric” pattern="[0-9]*"> allows for a degree of separation between how the user enters data (“input mode”), what the browser expects the user input to contain (type equals number), and potentially how it tries to validate it.
Which has incorrectly used closing quotes and correctly used straight quotes in the same code section, and then proper opening and closing quotes in the text section. I wonder how that happened.
[+] [-] mirekrusin|6 years ago|reply
[+] [-] nimish|6 years ago|reply
[+] [-] notriddle|6 years ago|reply
[+] [-] Fej|6 years ago|reply
[+] [-] calibas|6 years ago|reply
[+] [-] _v7gu|6 years ago|reply
[+] [-] eat_veggies|6 years ago|reply
[+] [-] BurningFrog|6 years ago|reply
The real problem is that there is no type for other "numeric" cases.
[+] [-] ArchReaper|6 years ago|reply
[+] [-] calibas|6 years ago|reply
Without any pattern specified, the code you posted will accept emojis as input, it's not a good choice for a numeric only field. It's also intended for phone numbers...
[+] [-] throwaway-q2233|6 years ago|reply
[+] [-] shakna|6 years ago|reply
How do you detect I'm using NVDA? It'll still look like Firefox. Or Chrome if I'm bypassing a broken UA detection.
Nowhere will you see NVDA, even though it is the problem.
[+] [-] inanutshellus|6 years ago|reply
[+] [-] klingonopera|6 years ago|reply
And shouldn't they be doing this anyway?
[+] [-] onion2k|6 years ago|reply
[+] [-] thawaway1837|6 years ago|reply
Server side sanitisation doesn’t address any of the accessibility concerns. Server side sanitisation doesn’t address the silent dropping of characters concern. Server side sanitisation doesn’t address the incrementing/decrementing the value accidentally concern.
That’s because the issues being discussed here are about creating a good UI that minimizes errors, and has little to do with sanitisation.
[+] [-] simion314|6 years ago|reply
[+] [-] jkrems|6 years ago|reply