step属性仅控制箭头增减步进和提交校验,无法拦截手动输入、粘贴或拖拽;真正限制小数位数需用type="text"+inputmode+pattern+JS实时过滤与提交前验证。

step 属性根本不能防止超精度输入
它只管校验和箭头增减,不管用户手动输、粘贴、拖拽——这些行为完全绕过 step 约束。你看到的“能输 3.1415926”不是 step 失效,而是它压根没被设计来拦截输入。
为什么设了 step="0.01" 还能输 1.23456789
浏览器对 type="number" 的约束分三层,step 只影响其中一层:
-
step控制:上下箭头步进值、提交时是否触发validity.stepMismatch -
min/max控制:边界校验(validity.rangeUnderflow/rangeOverflow) - 基础解析控制:是否为合法数字(
validity.badInput),比如输"1.2.3"或空字符串
只要输入内容能被 parseFloat() 解析成有限数字,step 就不会拦——哪怕你输的是 "0.0000000000000001"。
真正能控精度的只有 type="text" + JS 校验
想限制最多两位小数?别碰 type="number",直接换方案:
立即学习“前端免费学习笔记(深入)”;
- 用
<input type="text" inputmode="decimal" pattern="[0-9]*\.?[0-9]{0,2}">,移动端弹出数字键盘+小数点,pattern 限制最多两位小数(注意:pattern 不阻止粘贴,需 JS 补位) - 监听
input事件,用正则过滤:input.value = input.value.replace(/(\.\d{2})\d+|\.(\d{2})\d+|\.(\d{2})[^0-9]/g, '$1$2$3') - 提交前检查:
!/^-?\d*\.?\d{0,2}$/.test(input.value),不匹配就报错 - 需要数值计算时,别信
input.valueAsNumber(Safari 截断精度),老实用parseFloat(input.value)或decimal.js
step="any" 是个误导性选项
它只是关闭 stepMismatch 校验,不是打开精度闸门。实际效果是:
- 上下箭头退化为 ±1 整数增减(
value="1.5"点 ↑ 变成2.5,不是1.6) -
stepUp(1)和stepDown(1)也按整数走 - 用户仍可手动输入任意长小数,但表单提交不报错——业务层必须自己校验位数
- 旧版 Safari/Edge 可能直接忽略
step="any",回退到step="1"
最常被忽略的一点:无论你用什么方案,粘贴、第三方输入法、屏幕阅读器辅助输入,都会跳过所有原生约束。精度控制的终点,永远在 JavaScript 里。



















