The HTML step attribute
The HTML step attribute sets the interval between the values an input allows. With no min or value attribute, a number field steps by whole numbers, so 2.5 fails until you add step="0.01" or step="any". Time inputs count it in seconds, so step="900" means 15 minutes.
Overview
The HTML step attribute sets how far apart the allowed values of an <input> are. Spin buttons and sliders move by it, and an off-step value sets validity.stepMismatch unless a slider rounds it.
Seven input types accept step, each in its own unit. Number and range default to a step of 1. Date defaults to one day. Week and month, which desktop Firefox and Safari lack, default to one week and one month. Time and datetime-local count seconds and default to 60, one minute.
That default of 1 is why a number field with no min or value attribute turns down 2.5 but takes 2 and 3. A value of 1.0 still passes, because it equals a whole number. A step of 0.01 allows two decimal places, so 4.99 passes and 4.999 doesn't.
Number fields and sliders treat a value between steps differently. A slider rounds it to the nearest step inside min and max, with ties going up, so min="0" step="4" value="6" becomes 8. Chrome and Firefox keep such a value in a number field and report the mismatch instead.
The keyword any switches the step check off. The stepUp() and stepDown() methods then throw an InvalidStateError, since the field has no step to move by.
Syntax
<label for="price">Price</label>
<input type="number" id="price" name="price" min="0" step="0.01">
<label for="pickup">Pickup time</label>
<input type="time" id="pickup" name="pickup" step="900">
Values
| Value |
|---|
A positive number, or any. |
Example
<p><label for="price">Price in dollars</label><br>
<input type="number" id="price" name="price" min="0" value="4.99"></p>
<p><label for="rule">Step</label>
<select id="rule">
<option value="">none (default 1)</option>
<option value="0.01" selected>0.01</option>
<option value="0.25">0.25</option>
<option value="any">any</option>
</select></p>
<p id="msg" role="status" style="overflow-wrap:anywhere"></p>
<p>Change the step, then try prices such as 4.99, 4.75 and 5.</p>
<script>
const price = document.getElementById('price');
const rule = document.getElementById('rule');
function show() {
if (rule.value) price.step = rule.value;
else price.removeAttribute('step');
document.getElementById('msg').textContent = !price.value
? 'Enter a price to test it.'
: price.validity.valid
? price.value + ' passes with step ' + (rule.value || '1') + '.'
: price.value + ' fails. ' + price.validationMessage;
}
rule.addEventListener('change', show);
price.addEventListener('input', show);
show();
</script>
Best practices
- Prefer a real
stepsuch as 0.01 overstep="any"for money. With 0.01, a typo such as 4.999 still fails. - Watch pre-filled number fields. With no min and no step,
value="4.99"makes 5.99 valid and 5 invalid, whilestep="0.01"accepts both. - Target step errors with
:invalid, not:out-of-range. A value between steps inside min and max matches:in-range, because :out-of-range only covers values past the limits. - Stick to multiples of 60 for time steps unless people need seconds. Any other numeric step adds seconds to the time control, and so does a min or value that has seconds.
- Build custom plus and minus buttons with
stepUp()andstepDown(). They follow step, min and max, and take a count, sostepUp(4)moves four steps at once.























