:in-range和:out-of-range仅对type=”number”且含合法min/max属性的输入框生效;值为空、非数字或nan时不匹配任一伪类,safari旧版存在兼容问题,需js+服务端双重校验。

为什么 :in-range 和 :out-of-range 看起来没反应
这两个伪类只对带 min/max 属性的数值型输入框生效,且浏览器必须实际解析出有效数值范围。常见失效原因不是写法错,而是类型或属性缺失。
-
<input type="number">是前提,type="text"或没设type时完全不触发 -
min和max必须是合法数字字符串(如"10"),不能是空值、"auto"或含单位("10px") - 初始值超出范围时,
:out-of-range会立即生效;但用户清空输入框后,多数浏览器视为空值(not a number),此时两个伪类都不匹配 - chrome/firefox 支持稳定,Safari 在旧版本(≤15.4)中对
:out-of-range有延迟或不触发问题
:in-range 和 :out-of-range 的样式作用时机
它们反映的是「当前值是否在 min–max 闭区间内」,不是「用户是否正在输入」或「表单是否提交过」。值为空、非数字、或为 NaN 时,两个伪类均不激活。
- 输入
"5",min="10"→ 触发:out-of-range - 输入
"15",min="10" max="20"→ 触发:in-range - 输入
"abc"或删光 → 不匹配任一伪类(不是:out-of-range!) - 输入
"10.5",step="1"且min="10"→ 仍算:in-range(step不影响范围判断,只影响合法性校验:valid/:invalid)
和 :valid/:invalid 混用时的逻辑关系
:in-range/:out-of-range 只管范围,:valid/:invalid 还管类型、必填、step 等。两者独立计算,可能同时成立。
-
<input type="number" min="0" max="100" required>,输入"-5"→ 同时匹配:out-of-range和:invalid - 输入
"50.3",step="1"→:in-range为真,但:invalid也为真(因不满足 step) - 输入空值且
required→:invalid为真,但:in-range和:out-of-range都为假 - 别用
:out-of-range替代:invalid做通用错误提示,它覆盖不了空值、非法字符等场景
兼容性与真实可用的 fallback 方案
Safari 对 :out-of-range 的支持直到 ios 16.4 / macos 13.3 才修复完整。生产环境不能只靠 css 伪类做关键验证反馈。
立即学习“前端免费学习笔记(深入)”;
- JS 中应监听
input事件,用input.validity.rangeUnderflow/rangeOverflow主动判断并加 class - 服务端永远要重新校验范围,CSS 伪类纯属增强体验
- 若需兼容老 Safari,可改用
[value] + :not([value=""])结合 JS 动态 class 控制样式 - 注意:伪类无法通过
getComputedStyle读取,也不能用 JS 直接触发,只能靠用户交互或属性变更驱动
事情说清了就结束。