必须使用 type="number"(或 type="range")才能触发 :in-range/:out-of-range 伪类;type="text" 即使设置 min/max 也无效,因不进入数值校验流程。

必须用 type="number",type="text" 加 min/max 完全无效
浏览器只在原生数值解析上下文中才触发这两个伪类。type="text" 即使写了 min="1" max="100",样式也永远不会生效——它压根不进入范围校验流程。常见错误是把输入框写成:<input type="text" min="0" max="10">,然后纳闷为什么 input:out-of-range 没反应。
- 正确写法必须是:
<input type="number" min="0" max="10"> -
min和max值必须是合法数字字符串,比如"0"、"-5.5",不能是空、"auto"或带单位(如"10px") -
type="range"也支持,但实际几乎没用:它的值永远被浏览器强制截断到[min, max]内,:out-of-range几乎不会匹配
:in-range 和 :out-of-range 不处理空值、非法字符或 NaN
它们只判断「当前值是否为有效数字,且落在 min–max 闭区间内」。其他所有情况——空、" "、"abc"、"12a"、"--"——两个伪类都不匹配,元素回退到普通 input 样式。
- 用户清空输入框 → 多数浏览器视为“非数字”,既不是
:in-range也不是:out-of-range - 输入
"5.5",min="5" max="6"→ 匹配:in-range - 输入
"105",max="100"→ 匹配:out-of-range - 输入
"10.5",step="1"→ 仍匹配:in-range(step不影响范围判断)
JS 赋值不会自动触发伪类更新,必须手动校验
直接通过 JS 设置 input.value = "200",哪怕超出 max="100",样式也不会变——因为伪类依赖浏览器的表单校验状态,而 JS 赋值不触发该流程。
- 安全做法:赋值后立即调用
input.checkValidity()(仅刷新状态)或input.reportValidity()(弹原生提示) - 更贴近用户行为的做法:赋值后
dispatchEvent(new Event('input', { bubbles: true })),让浏览器按真实输入逻辑重走一遍校验 - 注意:不能用
getComputedStyle(input).getPropertyValue('border-color')判断当前是否在范围内——伪类状态无法通过 JS 读取
别指望它替代表单提交拦截,:out-of-range 不影响 checkValidity() 结果
:out-of-range 是纯视觉钩子,不影响表单验证逻辑。即使输入框显示红色边框,input.checkValidity() 仍可能返回 true,表单也能正常提交。
立即学习“前端免费学习笔记(深入)”;
- 它和
:invalid逻辑独立::invalid在required为空或step不合规时触发;:out-of-range只管数值是否越界 - 用户输入
"abc"→ 不匹配任一伪类,但checkValidity()返回false - 用户输入
"105"且max="100"→ 匹配:out-of-range,但checkValidity()仍返回true(只要不是required且为空) - 真正阻断提交,必须监听
submit事件 + 手动调用form.reportValidity()或自定义校验
:out-of-range 至少加背景色 + 边框色 + box-shadow,再搭配相邻兄弟选择器显示提示文字,比如 #age:out-of-range + #age-hint::after。Safari 旧版本(≤15.4)对 :out-of-range 支持不稳定,生产环境务必加 JS fallback。


















