:valid/:invalid 仅对含 required、type="email" 等原生校验属性的输入生效,纯 text 输入不触发;需配合 :user-invalid、:placeholder-shown 及 setcustomvalidity 实现精准状态控制。

为什么 :valid/:invalid 在输入框上没反应
浏览器只对带有 required、type="email"、type="url"、pattern 等原生校验属性的表单控件触发 :valid 和 :invalid 伪类。纯文本输入(如 <input type="text">)即使内容为空,也不会被标记为 :invalid —— 它压根没参与校验。
实操建议:
- 必须添加校验约束:比如用
required强制非空,或用type="email"触发邮箱格式校验 - 避免仅靠 JS 添加 class 模拟状态,否则会和原生伪类冲突,导致样式错乱
-
:invalid默认在用户**首次聚焦再失焦**(blur)后才生效,不是实时监听输入;若需输入中即时反馈,得配合:user-invalid(Chrome 102+、Safari 15.4+ 支持)
:valid/:invalid 的样式优先级和常见覆盖问题
这两个伪类权重等同于普通类选择器(0,1,0),但低于内联 style 和 ID 选择器。更关键的是:它们会被 :focus、:hover 等交互伪类“盖住”——如果你写了 input:focus { border-color: blue; },那即使当前是 :invalid,边框也不会变红。
实操建议:
- 把校验状态样式写在交互样式之后,例如:
input:invalid { border-color: #e53e3e; } input:focus { border-color: #3182ce; } input:focus:invalid { border-color: #e53e3e; } - 别依赖
!important,它会让后续调试变得不可控 - 注意
:invalid对未通过校验的字段始终生效(包括空值),而:user-invalid只在用户修改过且当前不合法时触发,更适合“输入中提示”场景
结合 :placeholder-shown 实现空值友好提示
当输入框有 placeholder 且内容为空时,:placeholder-shown 会匹配。这能帮你区分“用户还没输”和“用户输了但格式错”两种 :invalid 状态。
实操建议:
- 给空字段弱化提示色:
input:invalid:placeholder-shown { border-color: #cbd5e0; } - 只对已输入但非法的内容强化警示:
input:invalid:not(:placeholder-shown) { border-color: #e53e3e; } - 注意 Safari 对
:placeholder-shown的兼容性较好,但旧版 Edge 不支持;可加@supports条件包裹
JS 配合时如何避免破坏原生状态
调用 setCustomValidity() 是安全的,它会直接影响 :valid/:invalid;但直接操作 className 或 style 会绕过浏览器校验流程,导致伪类失效或不同步。
实操建议:
- 校验逻辑统一走
checkValidity()+setCustomValidity(message) - 提交前手动触发校验:
form.reportValidity(),它会激活所有:invalid样式并显示默认提示 - 不要在 input 事件里反复调用
setCustomValidity('')清空错误——这会让:invalid突然消失,打断用户感知;改用setCustomValidity(valid ? '' : '邮箱格式不对')
原生 :valid/:invalid 最大的限制在于无法表达“正在校验中”或“服务器返回错误”这类异步状态,这些必须交由 JS class 控制。混用时记住一条:浏览器管“格式是否合法”,JS 管“业务是否允许”,别让两者互相覆盖。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











