References

Beginner-friendly references for web development, with live, editable examples.

The HTML step attribute

Attribute All modern browsers
In short

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

Live 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 step such as 0.01 over step="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, while step="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() and stepDown(). They follow step, min and max, and take a count, so stepUp(4) moves four steps at once.

Frequently asked questions

Why does a number input reject decimals without step?
A number input's default step is 1, so without a min or value attribute 2.5 falls between allowed values. Set step to 0.01 for cents, or to any to accept every decimal.
What does step=any mean?
Setting step to any removes the step check, so the value no longer has to land on a step. Min, max and the input type's own format rules still apply.
What unit does step use on a time input?
On time and datetime-local inputs, step counts seconds, with a default of 60. Use 900 for 15 minutes or 3600 for an hour, since step=15 means 15 seconds.
Does step=0.1 run into floating-point errors?
Not in Chrome or Firefox, where a step of 0.1 accepts 0.3 and 0.7. In JavaScript, 0.3 % 0.1 returns 0.09999999999999998, so a script that checks steps with % rejects those same values.
Does step=0 turn the step check off?
No, a step has to be greater than zero. The browser ignores 0, a negative number or a word and uses the default step, while step=any turns the check off.