合法值由(min + n×step)≤max决定,而非从0开始;浏览器校验用(value−min)%step≈0(浮点安全),max仅截断不参与起点计算。

step 和 max 一起用时,合法值不是从 0 开始算的
浏览器判断一个值是否合法,看的是 (value - min) % step === 0(浮点安全版),而不是 “value 必须是 step 的整数倍”。max 只负责截断上限,不参与步进起点计算。比如 min="2" max="10" step="3",合法值是 2、5、8 —— 注意,11 被 max 挡住,但 2 是起点,不是 0 或 3。
常见错误是以为 step="2" 就能覆盖所有偶数,结果写 min="1",导致第一个合法值是 1,下一个却是 3,中间跳过了 2。这会让后端解析时误判“2 不在允许范围内”。
- 正确对齐方式:若要支持 2、4、6…,设
min="2" step="2"或min="0" step="2" - 若
min无法改动(如来自配置),JS 校验必须用Math.abs((val - min) % step) < 1e-10,不能直接val % step - Chrome 会在 input 失去焦点时自动把非法
value修正为最近合法值(如value="7"在min="2" step="3"下会被改成 8);Safari 可能静默保留,导致提交失败
max 不等于“最大可显示值”,它会砍掉超出的步进点
max 是硬边界,不是提示。即使数学上 min + n × step 算出来刚好等于 max,也必须满足 ≤ max 才被接受。例如 min="0" max="10" step="3",序列是 0、3、6、9 —— 12 超了,直接丢弃,不会出现 10。
更隐蔽的问题是:当 min + n × step 无限逼近 max 却永远不等于它(比如 min="0" max="1" step="0.33"),不同浏览器可能生成不同长度的合法值列表,甚至触发渲染卡顿(尤其 max 很大、step 很小时)。
立即学习“前端免费学习笔记(深入)”;
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
- 调试方法:在控制台运行
Array.from({length: 20}, (_, i) => min + i * step).filter(x => x <= max),看实际有哪些点 - 避免
max="100000" step="0.01"这类组合,改用整数缩放:min="0" max="10000000" step="1",JS 层除以 100 显示 - 表单提交前调用
input.checkValidity(),比等用户点提交更快暴露validity.rangeOverflow或stepMismatch
type="range" 和 type="number" 对 max+step 的响应方式不同
type="range" 的滑块视觉上可以平滑拖动,但最终取值一定落在 min 到 max 之间且符合 step 对齐的离散点上;type="number" 则只在校验环节(提交、失焦、调用 checkValidity)才强制匹配,输入过程中用户仍可键入任意数字。
这意味着:同一个 min="0" max="5" step="0.5",在 range 中你拖不到 3.3;在 number 中你可以输 3.3,但提交时会报错 stepMismatch。
- 移动端键盘弹出时,
type="number"的软键盘可能只显示数字和小数点,但不阻止用户粘贴 "3.333" -
type="range"配合<output for="id">是最轻量的实时反馈方案,无需 JS 监听 —— 但前提是max和step已设好,否则<output>显示的可能是非法中间值 - 不要给
type="text"加step,它完全被忽略,连警告都没有
容易被忽略的兼容性细节:max 的值类型必须匹配 step 的粒度
max 必须是能被 step 整除的数值(逻辑上),否则最后一个合法值可能意外提前结束。例如 min="0.1" max="0.9" step="0.2",合法值是 0.1、0.3、0.5、0.7 —— 0.9 被排除,因为 0.1 + 4×0.2 = 0.9,看似成立,但浮点误差可能导致 0.1 + 4*0.2 !== 0.9,部分浏览器会保守截断到 0.7。
时间类型更严格:type="time" 中 max="17:30" 和 step="60"(默认分钟级)可以,但 step="30" 就要求 max 必须带秒("17:30:00"),否则整个 max 属性失效。
- 验证方式:打开 DevTools,检查元素的
getAttribute('max')返回值是否和你写的完全一致(注意空格、大小写、格式) - 日期/时间类型中,
min/max字符串必须精确匹配step所需精度,少一位都算无效 - 旧版 Android 浏览器可能完全忽略
max,关键业务必须用 JS 双重校验


















