step仅对type="number"等少数类型生效,type="text"中无效;需配合min/max使用,且须注意浮点精度问题,关键场景应以JS和后端校验为准。

step 属性只对特定 type 生效,type="text" 加了也白加
很多开发者给 type="text" 或 type="tel" 的输入框写 step="0.01",发现上下箭头不出现、校验不触发、粘贴小数也不拦——这不是 bug,是规范行为。step 仅在 type="number"、type="range"、type="time"、type="date" 等少数类型中被浏览器识别并参与逻辑。其他类型会完全忽略该属性,DevTools 里能看到它,但毫无作用。
真正想控制房贷利率、折扣、价格这类数值输入,必须用:<input type="number" step="0.01">。别试图“兼容旧习惯”保留 type="text",那等于主动放弃原生步进和校验能力。
min/max 不配齐,step 就是摆设
step 本身不定义合法范围,它只规定“从哪开始、每次跳多远”。没有 min 和 max,step="0.01" 在 type="number" 下允许的值是从负无穷到正无穷的所有 0.01 倍数——这显然不是业务想要的。
- 房贷利率:用
min="3.00" max="6.50" step="0.01",注意min和max必须带两位小数(写成"3"或"6.5"会导致部分浏览器校验异常) - 折扣输入:用
min="0" max="1" step="0.01",min和max写整数即可,因为 0.01 步长天然覆盖 0.00~1.00 - 整数计数器:用
min="0" max="100" step="1",别漏掉min,否则用户能输 -999999
还要留意:浏览器校验时会检查 value 是否满足 value === min + n × step(n 为整数)。如果初始 value="4.355",而 min="3.00" step="0.01",Chrome 可能静默修正为 4.35 或直接标红,行为不一致。
立即学习“前端免费学习笔记(深入)”;
用户粘贴“4.355”或输入“4,35”,step 一概不管
step 不拦截键盘输入,不处理粘贴,不识别千分位逗号,也不做四舍五入。它只在两个时刻起作用:① 点击上下箭头或滚轮增减时;② 表单提交或调用 checkValidity() 时触发 stepMismatch 错误。
这意味着以下情况完全绕过 step:
- 用户复制粘贴 “4.355” 到利率输入框 → 浏览器接受,直到提交才报错
- 用户输入 “4,35”(欧洲格式)→
valueAsNumber为NaN,校验直接失败 - 用户敲 “4.350000000000001” → 浮点误差导致
stepMismatch,即使看起来合法
所以必须补 JS:
监听 change(非 input,避免光标跳脱):const v = parseFloat(input.value); input.value = isNaN(v) ? "" : v.toFixed(2);
服务端也必须重新解析并截断到两位小数——前端 step 是提示层,不是防线。
移动端 Safari 和旧版 Android WebView 对 step 支持极弱
iOS Safari 在 type="number" 上基本不显示上下箭头,step 校验只在提交时发生,且对浮点精度更敏感;某些 Android WebView 甚至完全忽略 step,允许任意小数输入。
这不是配置问题,是渲染引擎限制。因此:
- 别依赖
step实现核心业务逻辑(比如“必须是 0.01 倍数”) - 对关键字段(如金额、利率),JS 格式化要强制执行,不能只靠失焦时校验
- 考虑降级方案:检测
!input.checkValidity() && input.validity.stepMismatch后,用reportValidity()主动提示,而非静默修正
最常被忽略的一点:你写的 step="0.01",浏览器内部是用二进制浮点运算比对的。0.01 无法被精确表示,所以严格校验时可能出人意料地失败——与其死磕 HTML 属性,不如把精度控制收归 JS 和后端统一处理。



















