The number input is the worst input
My personal pet-peeve is devs using the number input for things that contain digits but aren't "numbers" (credit card numbers, 2fa codes, postal codes etc)[0]. Number input provides a lot of footguns and you're usually better off using something else.
[0] https://kilianvalkhof.com/2022/css-html/are-you-sure-thats-a...
> The Gov.UK article mentions a possible solution: Using <input type="text" inputmode="numeric" pattern="[0-9]*"> is a nice option for integers, but it won’t work for floating point decimal numbers.
Note that there's also an inputmode="decimal" option which does have a decimal-point on Android and iOS
Really the answer is just, "don't use number most of the time, use regular text with the appropriate inputmode". The inputmode abstraction is better than the type abstraction; it lets you specify what you really care about most of the time (mobile keyboards) without a bunch of extra constraints bundled in there
The stepper buttons on the number input are infuriating. They're far too small for anyone to click on, nobody uses them, and they look bad.
Invariably, a designer/PM/someone will come back and say "Is there any way we can get rid of those stepper buttons on the right?" and then it gets changed to a text input with JS validation.
This sounds like victim blaming devs for correctly calling things numbers, but the expected correct answer is something else. There shouldn't be a guessing game as to what the most correct name is that causes everything else to be wrong.
The true fault here is ambiguous naming conventions that become booby traps.
Should we be blaming people for trying to pull open a door that has a pull handle even though there's technically "push" writing on it? It's just so convenient, as the door maintainer, to have just one type of door, though. Am I so out of touch? No, it's the users who are wrong!
Aside from redesigning a lot of things like this that could've been implemented better, we need to do better to avoid ambiguous naming. We should adopt more verbose naming standards. In this case, we could get rid of literal "number" to replace with "number-incremental," "number-money," "number-scientific" etc.
If people try to use just "number" and see it doesn't work, they should be able to quickly find the correct thing without having to decipher a made up nonsense name like "lambda" or scrolling through an alphabetical list of input types and having to spot every possible number type, read its description, and then compare every result to determine the actual correct one.
Yeah, developers can learn with time and it's good to know all the different options... But why aren't we setting people up for success in the first place?
The worst number input that I've seen is some Windows input, in which the value must always be valid and in the allowed range. So, say, the current value is ‘300’ and you want ‘100’—but you can't backspace over the ‘3’ and enter ‘1’. If the value is ‘350’ and you want ’100’, you can't even select ’35’ and type ‘10’, because the input will freak out midway and immediately replace the value with the allowed minimum. Moreover, how do you even type the number you want if the input can't be empty? If the minimum is 20, you can't ever type anything from scratch without doing some select-replace gymnastics, because every digit will be immediately replaced with the value 20.
Can't remember which app it was, and if it was a standard input from one of the dozen MS frameworks—but the testers on it must've been mightily incompetent. Imagining for a second that someone worked on that is like catching a glimpse into an abyss of pure stupidity. After this horror I'm quite relaxed about problems with inputs that at least allow me to type the damn number.
It was a nice idea initially but implementation was rather dramatically more complicated than one would think (or at least than I thought it would be) The article mentions some issues but the most horrific one is missing:
If you focus the input field, hold the pointer over it and move the scroll wheel the value is rounded off, increased or decreased. There are 2 gotchas here.
Thus I found myself filling out a form that has to be filled out with the utmost accuracy. I look over the values again and again until the paranoia of potential financial disaster is sufficiently comforted. My eyes circle from field to field 6-10 times. (I'm never again going to make a mistake with this form ever again, enough is enough)
I then scroll to the submit button.
You can imagine what happens next, it involved a lot of adrenaline. One of the fields had changed, it was lower than before and everything behind the decimal point was unchanged. To make matters worse, I had no idea how this happened.
Next time I check all the values 20 times, scroll to the submit button and check the visible values again. So far so good?
I keep doing this and eventually it happens again!
It wasn't until the 5th time I finally deciphered what was going on.
There should be seperate types:
We need 2 different input keyboards on mobile: it should not be possible to type a dot if the input must be an integer.<input type=integer> <input type=float>
Currently seems to difficult to get a simple integer input: Chrome and Safari does not interpret step=1 as "no decimals".
Also: the up/down buttons should go. That should be an explicit option as they don't make sense in most cases. Might have a type=count for that.
Although I agree with the point made in this case about the number input (provided "inputmode" is set so a mobile device presents the right kind of keyboard), this kind of thinking drives me nuts:
> As a programmer, you might find this acceptable, but there’s a good chance your designer and/or product manager will not.
I couldn't care less if a designer is unhappy with the native functionality my browser exposes, it's called a user agent for a reason. They probably aren't happy with my custom style sheet either and this idea that designers' whims can override user preferences needs to stop.
The suggestion about using pattern="[0-9]*" will cause problems if your users copy-n-paste (or just type) a number with thousand separators.
People are probably used to providing input in a way to make the stupid computer happy, but that friction need not exist.
> Imagine a software tester finds this issue and logs a bug. Imagine the product manager hears about the bug. Imagine discussing this bug during sprint planning, but then pleading your case to that same product manager: “This is an edge case and the number will still be validated on the back end.” And besides, you said this was MVP and this “bug” is actually standard behavior of the number input. Imagine losing that battle and having to fix it anyway.
I felt sick reading that. We've all been there.
It also responds to the scroll wheel in some browsers, which sounds like a nifty feature except that we started receiving sporadic complaints and bug reports from users who insisted that forms were being submitted with slightly incorrect numeric values.
I spent an embarrassingly long time trying to track down some bizarre number parsing bug or obscure culture-specific behavior before realizing it was actually just users' cursors being over the number input while they tried to scroll, causing them to inadvertently change values just before submitting the form.
You want a real challenge? Build a number input that handles localizations, some countries use "," to separate decimals, and allow displaying thousand seperator automatically while typing, but read the value as a normal number during submit.
So something like "12.400,56" turns to 12400.56 and vice versa.
Also, is it just me or does this article seem to be a bit of an ad for "keenforms"? Its mentioned multiple times.
I just ran into this, I thought it would be nice to use a number input for relatively large numbers in a form, but then a user asked for a thousands separator.
I ditched the number input.
The number input should have been called “scalar stepper”. It’s genuinely useful when you have a scalar parameter and want the user to be able to increment and decrement the value with a given step.
A lot of confusion around this is because there isn't a general understanding around whether <input type="number"> represents a strict numeric value or if just the input interface should be a numpad instead of a full keyboard
The article lays out a lot of good points, though I think a lot of them can be summarized more as "here are things you may not have realized about the number input, so use it accordingly" rather than "it's the worst."
> The built-in validation is visually inconsistent to whatever UX when you are building for your app.
To me, this is the kind of thinking that takes Web 2.0-isms too far and makes for actually really shitty UXes. (And yes, of course, I know that the responsibility for these peeves lies with product managers, designers and the like _as well as_ developers).
I do not need a picker to pick my state. I know what f---ing state I live in. I do not need to review a list of all states, hoping I'll know it when I see it. In fact, for a semi-structured and rather complicated piece of data like an address, why force the user to partial-parse it anyway? No, the fact that you can type the first letter does not help. Just let me type the abbreviation. I know what it is! I f-----g live here!
I know how to type a g-----n address, especially my own, and it's likely that, unlike you, I actually know how to do it correctly. You know, where my ward goes? Ward? You didn't think of that? My fractional street number or the fact that I don't have one?
I do not need a calendar widget to pick my birthdate, especially when the calendar invariably starts with today and does not offer a straightforward way to type the date in my local format. I know when I was f---ing born. I do not need to look at a calendar and think "Hm, I know it was a Wednesday... maybe some time in the '90s? Better click the tiniest f---ing left-guillemet « I've ever seen 360 f---ing times and then maybe one of those months will ring a bell!"
And also, run your braindead validation when I'm well finished entering my information. You do not need to red-highlight the field just because I put the point somewhere else outside of it. You do not need to give me a popup for every number in my phone number until there are ten digits. You do not need to confuse me by sometimes filling in phone number delimiters as I type, and sometimes prohibiting them from appearing at all. I've had two different phone number fields on the same form behave in both of these ways!
Thinking of form-filling-out as a "user experience" or "live interaction" is okay, I guess, but it can't dominate your thinking to the point that you lose why it's a "form" in the first place. There are lots of use cases that really are analogous to filling out a form, I think a lot of web sites could do a better job of keeping the power of that analogy and using dynamics to enhance it.
The screenshot of this article contains an interest rate input field. The prompt in that field says "enter the interest rate, i.e. 3.25." The use of 'i.e.' (Latin id est, meaning 'that is') is a common error in such prompts. I think they meant 'e.g.' (exampli gratia) meaning 'for example.'
That aside, the presence of the decimal point raises four somewhat problematic questions: (1) how many decimal places are you going to allow on input? (2) how many decimal places will you display back to the user after they enter more decimal places than the typical user is expected to enter? (3) how many decimal places of the input will the application actually use in such cases? (4) How wide do you make the field to display the interest rate, and what do you do if the user enters something that won't fit there?
If you are writing software that should match the practices of more than one financial institution (bank, finance company, insurer, brokerage house, auditor, government regulator ...), the answers to those questions may be all over the map, and the number input widget probably will make it all an even bigger mess.
Let’s throw the baby out with the bath water.
Highly specific types are very useful on screen-limited mobile devices as they allow software developers to implement very specific controls for them.
It ticks me off that now I have to lose my 10-digit input keyboard for these fields and have to use the tiny on-screen keyboard for everything.
Reading the article and the linked UK.gov article, it seems like there are two issues: (1) lack of more specific types leading software developers to (2) make bad decisions related to the number type for things that are numeric but not countable numbers.
How about we just add a few specific types, or a subtype mechanism.
Eg specific types for dates, PINs, and so forth.
We would also need to add either a non-countable number type or a subtype of the existing number type. Under the hood it could even just be implemented as a string limited to digit characters, and would be usable for zip codes, etc.
Frontend problems really are something else. First, a number may include letters and does not correspond to real numbers. Second, JS thought it was a good idea to not care about the datatypes. Then the worst. The mess created by decimals and commas having different meanings in different langs and cultures. A bug I see a couple of times per year and a freaking terrible one cause users enter decimal numbers that are 100 times smaller or bigger than intended.
FYI - I wrote the article, happy to answer any questions
Off-topic, but why am I confirming my nonchalance about cookies on Stackoverflow/Stackexchange sites like three times every week?
The first bunch of times I could handwave it off as a result of Stackexchange having hundreds upon hundreds of sub-sites, but that doesn't work months into the deal. It's not like I'm on a mission to visit all those sites.
I ran into an annoying limitation of number inputs. I want to create an input where users can step up or down by 0.5 at a time. And I want to make it so that if the number starts out as something that does not divide by 0.5, clicking the step buttons will first round up or down to the nearest multiple of 0.5. Well tough luck, that's not possible. If the number input starts with the value 0.01 and a step of 0.5, then 0.0 and 0.5 are not valid inputs, -0.49 and 0.51 are. And if I instead change the step to 0.01 to make sure 0.0 and 0.5 even become valid inputs, then the steps are super small and inconvenient for my use case, basically forcing the user to type the number instead of using the step buttons.
Yeah no. Drives me nuts on the phone when people don't use the numbers field, so the VKB is not in the number pad mode automatically.
A QWERTY vkb in numbers / symbols mode have tiny number keys compared to a number pad.
If browsers validate differently, then fix them.
If a non-developer calls it a "<something> number" it's definitely a string for me. Even if you need to occasionally perform arithmetic on these "numbers", you could still store them as strings and parse on-demand.
In my experience, performing a culture-specific decimal.TryParse() at form submission time is the most robust way to validate something like a wire transfer amount. You can also do regex replace javascript stuff, but there are always some dragons in that realm (especially as you cross borders). Your backend is almost always going to be a better place to parse and verify user input.
Some of these problems could be solved by having frontend validation on a number input.
Regardless, I think the award for worst input goes to "datetime-local". The MDN page for it even says "Because of the limited browser support for datetime-local, and the variations in how the inputs work, it may currently still be best to use a framework or library to present these, or to use a custom input of your own". Followed by the date and time inputs, which are a real pain to work with.
undefined
I’m surprised at how bad native widgets are in general. They’re inconsistently styled, ugly, hard to override, and not all that usable. It’s nice that they have built in a11y support, but that’s about all they’ve got going for them.
I wish there were a web standard for modular, customizable, styleable inputs and pickers. It would eliminate a lot of needless wheel-reinventing and also make the web more accessible.
undefined
Often when I use number-input it's because I want numerical keyboard when people interact with it on a smartphone.
Yes, input type="number" is not the best, but when I ask for 2FA codes or credit card number a metric keyboard makes sense. And this is currently the best way I know to achieve it.
> I won’t pretend to be the expert on all things related to forms
Indeed. All of the issues the author is experiencing can be easily fixed with simple and readily documented javascript methods:
> When the number input contains an invalid value and you retrieve the value, you get a blank string
> Valid numbers include more than just digits (i.e,. scientific notation like the letter e).
> Different browsers accept different characters
Use inputElement.valueAsNumber and stop worrying.
If you send the form unaltered (that is, without intercepting the submit event), use a custom validator.
https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputEl...
> Min/max limits can be bypassed
Use frontend validation, e.g. inputElement.validity
https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Cons...
There are plenty of weird form elements out there, but input type=number is actually one of the better one. But the author is definitely very right about one thing:
> You should only use the number input when dealing with mathematically relevant numeric values
Mathematically relevant might be to strict. I would say that if ordering the numbers makes sense, then input type=number most likely makes sense as well. If your data is simply represented by a number (e.g. zip codes; 90210 < 98112 is a weird statement) input type=number is the wrong choice.
undefined
HTML inputs have APIs for checking their validation state. The input returning "" in invalid state is easy to test for:
const num = numInput.checkValidity() ? numInput.value : 0; // or some other default
a fun one I've found is that the Samsung keyboard on Android won't let you input negative numbers... they just omitted (-) entirely from the layout.
And the search input doesn't allow disabling auto-uppercase.
really nice ad for Keenforms!
undefined