Black and white close-up photograph of a curled tape measure

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 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.