The spec, purposefully, stops short of telling implementations (browsers) how to handle UI. In this article we’re looking specifically at <input type="number">
, and you might be surprised to learn that the spec specifically says:
This specification does not define what user interface user agents are to use.
It goes on to explain that different languages, cultures, and regions might have good reason to handle numeric inputs differently. So browsers are on their own here, and perhaps this time unsurprisingly, there are quite a few different approaches to the UI. Let’s take a look.
The Markup
<form>
<label for="age">Enter your age</label>
<input type="number" id="age" name="age">
</form>
This produces a simple form with one single input that accepts numeric values. I added some CSS for presentational purposes in the demos that follow, but this is the basic HTML markup we’re looking at.
How Internet Explorer Handles It
Internet Explorer offers the simplest default presentation among desktop browsers. The input looks like any other form input that accepts text. In fact, IE is making no user interface decisions for us at all, except the ability to clear the input once something has been entered. That’s a handy little feature, and one that other browsers do not include (although it’s sometimes seen on type="search"
inputs).
How Firefox Handles It
Firefox introduces UI that IE does not: spinner controls. These controls include up and down arrows that increase and decrease the numeric value of the field when clicked, respectively.
Removing the controls can be accomplished with a little CSS using the appearance
property:
/* Remove controls from Firefox */
input[type=number] {
-moz-appearance: textfield;
}
While that does a nice job of removing the controls, it appears we have no control over the design of them.
How Safari Handles It
Firefox and Safari are similar in how they treat numeric inputs. Both include spinner controls and both leave out the clearing UI seen in IE.
We can also remove the controls from Safari, but differently than Firefox using a method that tackles the Shadow DOM:
/* Remove controls from Safari and Chrome */
input[type=number]::-webkit-inner-spin-button,
input[type=number]::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0; /* Removes leftover margin */
}
Another element that we can style in the Shadow DOM is the invisible box around the number:
/* Adds a box around the numeric value in Safari and Chrome */
input[type=number]::-webkit-textfield-decoration-container {
border: 1px #ccc solid;
background: #efefef;
}
Might be useful, or it might not. Either way, it’s nice to have a little more design flexibility in Safari (and Chrome) compared to what we’ve seen so far.
How Chrome Handles It
Chrome sort of falls in the middle of the crowd. At first glance, we’re presented with a simple form input. Then, just as the cursor moves over the field, the same controls in Firefox and Safari are displayed.
Again, it’s interesting and worth noting that Firefox, Safari, Chrome and Opera have decided that quantity controls are enough of a benefit to user experience that they include them where IE has left them out. Then again, Chrome takes the middle ground by revealing the controls on hover as opposed to displaying them by default.
What if we want Firefox to behave like Chrome and display the controls on hover? We can remove the controls from Firefox like we did earlier, then re-apply them on :hover
and :focus
:
/* Remove controls from Firefox */
input[type=number] {
-moz-appearance: textfield;
}
/* Re-applies the controls on :hover and :focus */
input[type="number"]:hover,
input[type="number"]:focus {
-moz-appearance: number-input;
}
While Chrome and Safari might not be as similar as we might expect, they do share an ability to style and manipulate the input using the Shadow DOM elements. In fact, the same techniques covered in the Safari section apply to Chrome as well.
How Opera Handles It
Opera handles numeric inputs exactly like Chrome. That should come as no surprise since Opera adopts the same Blink rendering engine as Chrome. That means that the same CSS tricks to hide and style the input in Safari and Chrome also apply here with Opera.
Since Opera only recently updated to Blink, it’s interesting to see how its last pre-update version, Opera 12, handles numeric inputs.
The difference here is how the the controls float outside the input. Where Firefox, Safari, Chrome and the latest Opera place the controls squarely inside the input, Opera 12 has them completely outside of the field. Even more notable is how Opera has decided to place borders around the controls. This creates what appears to be a full-fledged user interface complete with buttons that extend the width of the input by default.
Removing the controls from Opera is no easy task and can only be removed by changing the input type to text
in the HTML and restricting the pattern of accepted characters strictly to numbers:
<form>
<label for="age">Enter your age</label>
<input type="text" pattern="[0-9]*" id="age" name="age">
</form>
Another difference is how the number is right-aligned. This is sort of reminiscent of how Excel automatically aligns numeric spreadsheet cells to the right. All other browsers keep the text aligned to the left, so we can force Opera to do the same using CSS:
html:not([dir="rtl"]) input {
text-align: left;
}
This snippet searches the DOM for any input that is not set right-to-left and forces the text to the left. This would be applied globally as written, but could be modified with more specificity, if needed.
One final detail worth noting is all the highlighting that’s happening on :focus
. Opera applies what appears to be the heaviest amount of styling when the field is targeted, all the way down to the quantity controls, which have their own active states when clicked.
How Mobile Safari and Android Handle It
Mobile Safari and the Android Browser are very similar when stacked head-to-head. Both behave much like IE in that they offer no controls directly on the input, but they also diverge from IE in that they provide no added user interface for clearing the input once something has been entered. In this sense, the mobile browsers offer the simplest default implementation of the entire set.
These browsers recognize type="number"
and instantly serve a numeric keyboard when the input is in focus. That’s pretty cool and serves as an excellent reminder that adding the proper type
to any form field is a good practice for good user experience.
The Results
Here’s a summary of the findings covered in this post.
Does it Have? | IE | Safari | Firefox | Chrome | Opera | iOS | Android |
---|---|---|---|---|---|---|---|
Spinner Controls | No | Yes | Yes | On Hover | On Hover | No | No |
Clearing Control | Yes | No | No | No | No | No | No |
Left Alignment | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
Focus Styling | On Hover | Yes | Yes | Yes | Yes | No | No |
Keyboard Commands | Yes | Yes | Yes | Yes | Yes | No | No |
Shadow DOM Control | No | Yes | No | Yes | Yes | No | No |
In Conclusion
It can be frustrating when browsers behave differently. We’ve been dealing with that in various ways for a long time. That’s how hacks—err, tricks— are discovered.
The interesting thing a comparison like this reveals is how these differences have an impact on user experience. If we were to create a numeric form input and rely on browser defaults to handle the display, then it’s very possible that two different visitors to the site will have two totally different experiences. Although that experience might also be consistent for them across sites, since that user likely sticks to one browser.
How do you feel about these UI differences? Do you have a favorite? Have you tried overriding them? What can we do with JavaScript here? Please share in the comments.
Bowl me over, but I think IE got this one right. I really dislike having to use a form element when I can just type something in. (Having to use a dropdown to fill in the state in my address is a pet peeve.)
Chrome’s implementation is the worst. Can those controls be any smaller? That’s horrible for accessibility.
In all of the mentioned browsers you can also just type in a number.
I guess the screenshots where made on a Mac, the spinner buttons are a lot smaller there than on my Windows versions of that browsers, but also more consistent accross different browsers.
Very interesting stuff, Thanks for sharing :)
@RioBrewster 110% agree.
IE nailed it on this one, the clearing ‘X’ is all is needed in this scenario. Quantity controls are unnecessary, they ask too much work from the user.
Firefox’s, Chrome’s, Safari’s quantity controls are just too damn small, next to impossible to use, too much work trying to aim your pointer to the right arrow.
No love for up and down arrows? One thing I certainly like about showing them is that as a user can see what the expected input is without reading or knowing any of the context(I see the flaw in the argument but I still believe there is something to it).
I don’t think many feel forced to actually use the arrows.
And a tip for RioBrewster(Although I totally agree it can be annoying). If you type your state fast enough it will select the correct option.
@Rene,
Typing the state only works if your state is the first that starts with that letter. So if I type TX, I get TN. When I lived in CA it wasn’t a big deal because I didn’t have to scroll the drop down and/or typing “C” gave me CA.
I guess this is one of the few advantages CA has over Texas. ;^)
I think it depends on the browser. Some let you type the search-term (“T”, “X”) and it will jump to the item. Others, the first “T” will take you to the first “T” entry and then subsequent “T”s (in short order) will take you to subsequent “T” entries. As a TX resident, I’ve grown accustomed to typing “TT” to jump to my state entry. At least in FF.
@RioBrewster, in the state dropdown you can also continue to press T to cycle through other states that start with T as well.
We’ll have to agree to disagree here.
If my number input is only using integers and the step attribute is set to 1, the controls may seem superfluous. When the step is anything other than 1 the controls really help communicate what that particular field sees as a valid entry.
Also, the fact that the controls can be easily hidden with CSS gives us the best of both worlds, so yay options!
Any thoughts on using type=”tel” to bring up the numeric-only keypad? It’s much better than just the numeric/symbol keyboard, but I also don’t want to be writing bad markup.
I too feel a bit “dirty” doing this, however those up and down controls really irk me. The problem with
number
is that a number can have symbols in it, so you can’t really show just numbers.You must use
pattern="\d*"
to specify 0 or more digits only. This will bring up the correct keypad.The “pattern” argument not always works. One time I was developing a number field where the user have to enter a decimal number. Some Android versions don’t show the correct keyboard. It shows the phone keyboard, but I wanted it to show a keyboard with dots (or commas, in some languages). Even if the device had the latest version of Android, the manufacturer (like Samsung) can change the default keyboards and don’t implement it properly.
How the system was made exclusively to Android users, the solution was weird. I have to use type=”tel” and a javascript to automatically add the decimal separator after the user type 2 digits http://jquerypriceformat.com/#examples
Very good comparison but I miss an Android screenshot.
What about up/down arrow support to increase/decrease the number?
I mean up/down keys
Mousewheel up and down also works in some browsers
Chrome supports both up and down arrows and mouse wheel.
One other trick: if you do:
Mobile Safari will give you a 10-digit keypad as your keyboard.
pattern="[0-9]*"
will work as well.Makes absolute no sense to me these arrows.
What about 0.06 or +1.6e-2 or 1.55 and so on.
All numbers right ? What should the increment be ?
You must use step=”any” and the increment will be in the 1’s place and increment by 1. If you try to increment with step=”2″ you will lose the floating point number (and your first increment will round)
1.6e-2 is a shorthand notation, not technically a number. Or is my understanding of math wrong?
Oh, I just learned you can target decimal places with step… heh.
step=”0.01″ would make the hundredths place increment by 1. :)
Hope I helped!
The step attribute defines the amount of increase/decrease performed by the arrows. Min and Max can (and probably should) also be specified to define the range of numbers allowed.
If the step is left empty, it often defers to the min value to determine what the step should be.
just FYI;
If you pass a literal like +1.6e2 to a FORTRAN back end it will be interpreted
as a single precision real number.
3.1415926535d+0 as floating point number and there is even
a Single Precision Complex ,like (3.2767e+2,-0.65e-2).
How FORTRAN deals with shorthand notation does not make shorthand notation a number. It’s a representation of a number that browsers don’t parse into a number. Just because certain programming languages parse it doesn’t change what it is.
Again, to my understanding. Not trying to be rude – just trying to explain the behavior.
This is exactly why browser defaults should not be overridden in nearly all scenarios, unless it’s more trivial (EG: color) or more practical for a use scenario changing the default of ±1 to ±5 or another increment (perhaps allowing tips in increments of $5).
Not only does the user probably stick to one browser – they visit other websites. If they visit another website and they leave this functionality untouched and you remove it you may have an issue on your hands with that user. :)
It looks like you’re testing this in Opera 12, which is years old… Why? Why not use the latest available version, i.e. Opera 28? Please consider re-running your tests and updating the compatibility table in this post accordingly, because at the moment it’s not exactly a fair comparison.
Echoing what Mathias said. Testing in Old Opera is akin to some developers wanting to test in Safari on their Windows machines and opening Safari 5.
There’s also no indication of support for this input in Old IE (caniuse reports that it was implemented in IE10).
Nice catch! That was definitely on oversight on my part and have updated the post to reflect the latest version of Opera. Thanks!
Great article for those of us who want to keep updated on how different browsers handles the new input types without having to do the job ourselves. I would love to see more of this.
I think there is a small mistake in the text.
How I interpret the CSS is that a html document that is not set to right-to-left will get the text-align: left for all input elements. Right-to-left documents, eg pages in arabic, will not be affected.
Ah, good call Martin. I had mistakenly left the word not out of that sentence and have corrected it–thanks!
In case anyone was wondering, this is how Windows Phone handles number input: http://i.imgur.com/8odp2Ig.png
It’s almost the same as Android, but it’s a bit simpler.
how to remove the styles from the date input in chrome?
None provide large enough enough click/tap targets for the up/down control. Opera comes closest.
I guess with the spinners it depends on what the number is used for. There was something that I created once (a color picker) where before type=”number” was supported, I tried to create my own spinners, so the user could easily make minor changes to the Red, Green and Blue field.
I think the key thing missing from these UIs is something to prevent the user from typing an incorrect value in the first place. It’s one thing to complain about bad input when the user tries to submit the form, but more user friendly to prevent the error in the first place. I, for one, would rather not be given the chance to make a mistake, than to be scolded for it!
We’ve been researching numeric inputs recently and a huge problem is these inputs will frequently null out the value if you enter in anything other than 0-9. So if you want to use this for a number that might need spaces or other delimiters, the input will break. Our current approach us to filter out any keystrokes other than 0-9 to prevent a disaster before it happens. Be good to test where this delimiter breaks things, in our initial tests, it was most browsers.