The HTML5 number
input creates a validated input for integers and floating point numbers in web forms. The basic syntax of the element is simple:
<input type="number" name="int">
Defaults & Accessibility
In most cases it’s a good idea to present a default value for the number
input; general accessibility principles also apply:
<label accesskey="b">
How many boys are brought to the yard by your milkshake?
<input name="boys" id="boys" type="number" value="3">
</label>
If a browser fully supports the input type, “spinner” UI controls are presented, which will raise and lower the value of the input. If the element has focus, using the up / down cursor keys and a wheel mouse will have the same effect. Note that not all browsers support this UI pattern: iOS 6, for example, supports the number
input but does not present up / down arrows, likely due to space considerations.
Limiting The Input
By default, the number
input will take an infinite range of values, including negative integers. In most cases, this range should be limited by using min
and max
attributes:
<input type="number" value="1" min="1" max="12" name="int">
As a broad rule, a limited number
input should support no more than a dozen valid integer values before adding some form of explicit direction: otherwise, you’ll tend to find that users click on the up / down arrows endlessly to reach a value, rather than typing it in directly. As an example, a control for a vehicle collision simulator:
<label>Enter the velocity of the car in kilometers per hour (0 – 120).
<input type="number" value="30" min="0" max="120" name="velocity">
</label>
The values can also be controlled by a step
attribute, which will force values into a particular progression:
<label>Crystalware must be ordered in pairs. Please enter the number you wish to order:
<input type="number" value="2" min="2" max="24" step="2" name="glasses">
</label>
Now the up-down arrows for the element will only generate even numbers. Using step
will also influence form validation: manually entering 3 into the example above should generate an error after the user presses the submit button.
By default, the number
input increments, decrements and validates whole numbers. step
also allows the field to generate and accept floating point values:
<label>Weight (kilos):
<input type="number" value="1" min="0" max="12" step=".1" name="weight">
</label>
Restricting Input to Valid Keys
One potentially confusing feature is that the number
input will accept text as entered data. While it will be flagged as invalid once the user submits the form, you may wish to avoid the possibility entirely by using JavaScript to filter any data entered into the field on keydown:
function isNumber(event) {
if (event) {
var charCode = (event.which) ? event.which : event.keyCode;
if (charCode != 190 && charCode > 31 &&
(charCode < 48 || charCode > 57) &&
(charCode < 96 || charCode > 105) &&
(charCode < 37 || charCode > 40) &&
charCode != 110 && charCode != 8 && charCode != 46 )
return false;
}
return true;
}
On the input itself:
<input type="number" onkeydown="return isNumber(event);">
This will prevent non-numeric characters from being entered into the field (decimal points excepted), while cursor controls and the return key will still work in the element as expected.
Similarly, it is also possible to manually enter numbers beyond the range of min
and max
into a number
field. Again, such entries will be flagged as invalid on submit; preemptively preventing this behaviour requires a little more JavaScript, which I would combine with the previous script above:
function isNumber(event, element) {
if (event) {
var max_chars = element.getAttribute("max").length;
var charCode = (event.which) ? event.which : event.keyCode;
if (charCode != 190 && charCode > 31 &&
(charCode < 48 || charCode > 57) &&
(charCode < 96 || charCode > 105) &&
(charCode < 37 || charCode > 40) &&
charCode != 110 && charCode != 8 && charCode != 46 ) {
return false;
}
if (element.value.length >= max_chars && charCode > 47) {
return false;
} else {
return true;
}
}
}
The HTML is modified to:
<input type="number" onkeydown="return isNumber(event,this);" step="1" min="0" max="99">
I’ll have more to say about charCodes and detecting keypresses in a future article.
Styling The Input
The number
input is automatically sized to accept a very high range of numbers, up to 1014, including scientific notation. Limiting the input with min
and max
should change the size of the element to fit the expected range, but you may want to provide a backup in CSS:
input[type="number"] { width: 2rem; }
Note that (at least officially) you cannot use the size
attribute to modify the appearance of elements in HTML5, as it is no longer valid.
The entire panoply of CSS can be applied to the number
input. In theory, the up and down arrows can also be styled, although our ability to do so is limited at the moment. The following CSS will remove the spinners in Webkit:
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
}
Alternatively, you could use a variation of the JavaScript above applied to a standard text input with a regular expression pattern, which will not show spinners by default.
<input type="text" pattern="[0-9]*">
Building Cross-Browser Compatibility
number
has touch-and-go support at the moment: some browsers support it fully (Chrome, Firefox 29+), others partially, and still others not at all. Implementations are still being worked on; the best solution I’ve found is a polyfill by Jon Stipe; the only disadvantage of which is a dependence on JQuery.
Photograph by Aaron Crowe, used under a Creative Commons Attribution-NonCommercial-NoDerivs 2.0 Generic license
Enjoy this piece? I invite you to follow me at twitter.com/dudleystorey to learn more.