Device-Bugs
Device-Bugs copied to clipboard
Safari 6 (Mac OS X and iOS) round long values inside input type="number"

- Reproducible on Safari 6, fixed in Safari 7.
- Firefox 47 exhibits the same issue if you set a super long value in JS a la
.value = "12341234123412341234"; - Firefox 47 on Android works as expected
Works as expected in Safari 7.
More useful discussion from @dmethvin here: https://twitter.com/davemethvin/status/751107262471606272
So the problem is that Safari 6 stores and displays the floating-point value rather than the string value, even though the unrounded string is a valid floating-point number per the html 5 spec (and thus can be kept as a string and converted to a rounded double-precision float when needed)? Browser bug sounds about right, maybe even browser quirk.
I believe that the browser should not be doing this per spec; however, note that this kind of use of <input type="number"> is invalid:
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 use type=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 a pattern attribute).
https://html.spec.whatwg.org/multipage/forms.html#number-state-(type=number)
Yeah, the docs seem pretty clear. If you actually want an IEEE floating point value out of the process this bug doesn't make that much difference. Trying to use a type=number input for other purposes is also risky since user input like "9e9" is valid.
Good conversation, thanks for chiming in. Really, the root problem is Android won't show the numeric keypad on Android unless it's a type of number - neither pattern="[0-9]*" (any pattern in fact) or inputmode="numeric" trigger the right keypad (thanks Google!).
So to launch the optimal keypad on Android, we've been trying to make the type=number work for us and there are lots of interesting issues like non-numeric characters can break the input in Firefox so we're filtering out any characters that aren't 0-9, etc. to avoid the situation @dmethvin (hi!) brought up. Yes, we know that the spec designed this only for capturing floating point values but we really want to have a decent UX for data entry and Android isn't doing us any favors.
You can get rid of the spinner buttons with this CSS on webkit and FF with a bit of CSS:
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
input[type="number"] {
-moz-appearance: textfield;
}
And we've added extra JS to ignore the arrow keys and other triggers that would increment/decrement the value. Fun!
Let's just say this is a messy situation. But I don't think the other answer (use tel) is any good either, at least semantically.
Thanks for the detailed explanation @toddparker! Yeah this seems like the perfect place to apply that inputmode=numeric attribute that nobody implements yet.
Just for fun, I wanted to see if the latest Android (6) finally supported inputmode http://jsbin.com/cukeha/
Nope:

Good ol number works tho:

Using tel just seems like such a bad option, even if it's more accepting of values. The keypad looks like a dialer rather than a numeric keypad here on latest Android which is confusing UX-wise


Additional Safari 6 test data (note that this input is only 16 digits long and is still rounded)
I'm pretty sure this is expected: double (64-bit float) can't store that much precision, only 52 bits of precision. That's between 15 and 17 decimal digits.
Worse, this doesn’t seem to be feature testable, given the following:
Safari 6 and Firefox 47
el.value = "12341234123412341234";- Field changes to render
12341234123412300000 el.valuereturns12341234123412341234el.valueAsNumberreturns12341234123412340000(note the four trailing zeros, as opposed to the five rendered trailing zeros above). This behavior is consistent cross-browser, even on browsers that don’t exhibit this truncating issue in the UI (Chrome).
Note that Firefox 47 exhibits the same behavior for the above feature test attempt, however operates correctly from a UX perspective: typing 12341234123412341234 manually into the field renders correctly.
More test data here:
- Rendered value is matches?
valuematches?valueAsNumbermatches? If does not match and rendered value also does not match, are they the same?- Value submitted to server matches?
Using the value "12341234123412341234" take the following two paths: setting value with JS or a user entered value. Interesting bullets are bolded.
Safari 6 setting value with JS:
- Rendered value mismatch:
12341234123412300000 valuematchesvalueAsNumbermismatch and does not match rendered value:12341234123412340000
Feature test would not work.
Safari 6 user typed value:
- Rendered value mismatch:
12341234123412300000 valuemismatch:12341234123412340000valueAsNumbermismatch and does not match rendered value:12341234123412340000- Successful form control value mismatch:
12341234123412340000
Firefox 47 setting value with JS:
- Rendered value mismatch:
12341234123412300000(Bugzilla Issue) valuematchesvalueAsNumbermismatch and does not match rendered value:12341234123412340000
Feature test would not work.
Firefox 47 user typed value:
- Rendered value matches
valuematchesvalueAsNumbermismatch:12341234123412340000- Successful form control value matches
Chrome 51 and Safari 9 setting value with JS:
- Rendered value matches
valuematchesvalueAsNumbermismatch:12341234123412340000
Chrome 51 and Safari 9 user typed value:
- Rendered value matches
valuematchesvalueAsNumbermismatch:12341234123412340000- Successful form control value matches
Verdict: close but valueAsNumber should probably be NaN
IE11 setting value with JS:
- Rendered value matches
valuematchesvalueAsNumbermismatch:NaN
IE11 user typed value:
- Rendered value matches
valuematchesvalueAsNumbermismatch:NaN
Verdict: this is how it should work in all browsers
FWIW per spec valueAsNumber should be converted to a floating point number (so by your account "incorrect") whereas value should just be the typed string.
@domenic Ah yeah, sorry. Will correct it to say “mismatched” instead of “incorrect”