:valid和:invalid在元素值通过/未通过约束验证时触发,初始空required字段默认为:invalid;需配合required、pattern等属性或setCustomValidity()才生效,且须确保原生表单提交流程。

什么时候:valid和:invalid会触发样式变化
这两个伪类只对具有内置表单验证能力的元素生效,比如 、、 等。它们不依赖 JavaScript,浏览器原生根据当前值是否通过约束验证(constraint validation API)自动切换状态。
注意:初始加载时,空的 required 输入框默认是 :invalid(哪怕用户还没输),这常被误认为“bug”,其实是规范行为——空值不满足 required 约束。
- 只有用户修改过值(
input或change事件触发后),:valid/:invalid才开始动态响应 -
type="text"没有内置校验逻辑,加:valid不会生效;必须配合required、pattern等属性才有意义 - 自定义校验需调用
setCustomValidity(),否则伪类不感知 JS 主动设置的错误
如何避免初次加载就显示红边这种干扰体验
直接写 input:invalid { border-color: red; } 会导致所有空的必填项一上来就是红色。这不是 bug,是设计使然,但用户体验差。
解决方案是加一层“用户已交互过”的判断,常用 :user-invalid(Chrome 102+、Firefox 119+、Safari 16.4+ 支持),它只在用户编辑过且验证失败时才匹配:
input:invalid:not(:user-invalid) {
border-color: #ccc; /* 初始态不强调错误 */
}
input:user-invalid {
border-color: #e53e3e;
}
兼容老浏览器可退回到 JS 控制 class:
- 监听
input事件,在首次输入后给元素加has-user-input类 - 把样式写成
input.has-user-input:invalid,绕过初始状态 - 不要用
focus做判断——获得焦点不代表用户输过内容
pattern 和 :valid 配合时容易忽略的细节
pattern 的正则默认是“全字符串匹配”,但很多人写 pattern="[0-9]+" 却发现输 "123abc" 也通过了——因为没锚定开头结尾。
必须显式加上 ^ 和 $:
<input pattern="^[a-z]{3,}$" title="至少3个小写字母">
否则浏览器内部等价于 /[a-z]{3,}/(子串匹配),不是你想要的“完全符合”。另外:
-
title属性会在验证失败时作为提示文案,别漏掉 - 空值对
pattern默认是合法的,除非同时加required - 正则中的
\d在某些浏览器(如旧版 Safari)不被pattern支持,改用[0-9]更稳妥
为什么提交时没报错,但 :invalid 样式却不出现
最常见原因是表单里混用了无验证能力的元素,比如用 检查点: 伪类生效的前提是浏览器真的执行了验证流程,而不仅仅是“看起来像表单”。,或用 type="button" 冒充提交按钮导致表单未真正 submit。
或回车,而不是 onclick 里手动 form.submit()(后者跳过约束验证) 包裹了所有需要验证的控件,孤立的 input 不参与表单级验证:invalid 是否被其他 CSS 规则覆盖(比如更高级的选择器重置了边框)form.noValidate = false
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











