:in-range没反应需先检查三件事:input缺少min/max属性、type非number/date/time类型、初始value为空;空值既不匹配:in-range也不匹配:out-of-range,须用户输入后才触发。

为什么 :in-range 没反应?先检查这三件事
:in-range 不是“写了就生效”的样式钩子,它依赖浏览器对输入值的实时数值判断。常见失效原因就三个:
-
input缺少min或max属性(哪怕只设一个也行,比如min="0") -
type不是number、date或time——type="text"加了min/max也完全无效 - 初始
value为空字符串("")或未设置:空值既不匹配:in-range,也不匹配:out-of-range,必须等用户输入后才触发
别用 JS 动态设置 min/max 后再指望伪类立刻响应——属性得在 DOM 渲染时就存在,否则 Safari 和部分 Android WebView 可能跳过初始状态计算。
:in-range 和 :out-of-range 的样式优先级怎么写才不打架
这两个伪类和 :invalid、:focus 共存时容易互相覆盖。关键不是堆叠权重,而是按语义分层:
-
input:in-range:not(:invalid)→ 合法且在范围内(主成功态) -
input:out-of-range:not(:invalid)→ 数值越界但格式正确(如输入150但max="100") -
input:invalid:not(:in-range):not(:out-of-range)→ 格式错误(如输入"abc")
直接写 input:in-range { border-color: green; } 很容易被后续的 input:invalid 规则盖掉。加 :not(:invalid) 是最轻量的隔离方式,比用 !important 可靠得多。
移动端真机上 :in-range 失效?查 WebView 版本
iOS Safari 自 iOS 10.3 起完整支持 :in-range,但旧版 Android WebView(尤其基于 Chrome 53 之前的系统 WebView)会完全忽略该伪类,连 CSS 都不解析。
验证方法很简单:在目标设备打开控制台,执行 document.querySelector('input[type=number]').matches(':in-range'),输入合法值后看返回 true 还是报错或 false。
兼容 fallback 方案只有两个实际可行路径:
- 用 JS 监听
input事件,手动切换.in-range/.out-of-rangeclass(注意要同步处理粘贴、拖拽等非键盘输入) - 放弃视觉反馈,只保留原生
setCustomValidity()提示(但无实时边框/背景变化)
别给 :in-range 加 animation,用 transition 更稳
:in-range 在每次输入后都可能反复进入/退出,如果配了 animation: shake 0.3s,用户输个 123 就会触发三次抖动,体验极差。
立即学习“前端免费学习笔记(深入)”;
正确做法是只过渡可缓动的属性:
border-color-
background-color(避免用半透明色,某些 WebView 渲染异常) -
box-shadow(慎用模糊值 > 4px,低端安卓机易卡顿)
示例:
input[type="number"] {
transition: border-color 0.15s ease, background-color 0.15s ease;
}
input[type="number"]:in-range:not(:invalid) {
border-color: #38a169;
background-color: #f0fff4;
}
input[type="number"]:out-of-range:not(:invalid) {
border-color: #e53e3e;
background-color: #fff5f5;
}
真正难搞的从来不是写对规则,而是当用户长按输入框唤出系统菜单、粘贴一串数字、或者用语音输入时,:in-range 状态是否还能跟上——这些边界场景下,JS 补位几乎是必选项。


















