:valid 伪类仅对含验证属性(如required、type、pattern)的表单控件生效,需同时满足“有验证语义+值符合规则”才匹配,不适用于普通元素或无验证约束的输入框。

valid 选择器只对表单控件生效,不是所有元素都能用
:valid 是 CSS 伪类选择器,它只在元素具有 required、type(如 email、url、number)等验证属性,且当前值通过浏览器原生校验时才匹配。普通 <div> 或未设验证约束的 <input> 即使内容“看起来正确”,:valid 也不会触发。
常见误用场景:
- 给
<input type="text">加:valid却没加required或其他验证属性 → 永远不生效 - 用在自定义组件(如封装的
<my-input>)上 → 浏览器不识别其验证状态,:valid无效 - 依赖 JavaScript 动态设置
value后忘记调用input.reportValidity()→ 状态未更新,样式不切换
必须配合表单验证属性才能触发 :valid 样式
只有当元素满足「有验证语义 + 值符合规则」两个条件时,:valid 才会生效。典型组合如下:
-
<input required>:空值为:invalid,非空即:valid -
<input type="email" value="a@b.c">:格式合法才匹配:valid -
<input type="number" min="10" value="15">:在范围内才匹配 -
<select required><option value="">选一项</option></select>:选中非空选项后才:valid
注意:pattern 属性也参与校验,例如 <input pattern="[0-9]{3}"> 要求输入三位数字,否则为 :invalid。
立即学习“前端免费学习笔记(深入)”;
:valid 和 :invalid 的样式切换是实时的,但不触发重排
浏览器在用户输入、失焦(blur)、或调用 checkValidity() 时同步更新 :valid 状态,样式随之变化。这个过程不引发 layout,性能开销极小。
但要注意几个边界行为:
- 初始加载时,若
input有value且符合规则,会直接进入:valid状态 - 用户删除全部内容后,
required字段立即变为:invalid;但非required字段(如type="email")空值时是:valid(因为空字符串本身符合 email 格式“可为空”规则) - 使用
setCustomValidity('')清除自定义错误后,会重新走原生校验逻辑,影响:valid结果
示例代码:
<input type="email" required placeholder="请输入邮箱">
<style>
input:valid { border-color: #4caf50; }
input:invalid:not(:placeholder-shown) { border-color: #f44336; }
</style>
不要用 :valid 替代 JS 校验逻辑
:valid 只反映浏览器内置校验结果,它无法处理业务级规则(如“密码需包含大小写字母”“用户名不能与邮箱相同”)。这类逻辑必须靠 JS 实现,并通过 setCustomValidity() 注入验证状态,否则 :valid 不会响应。
容易被忽略的一点是:setCustomValidity('') 表示“通过”,但只要传入非空字符串(哪怕只是空格),就强制标记为 :invalid,且会覆盖所有原生校验结果。
所以真实项目中常见写法是:
- 先用
checkValidity()获取原生结果 - 再叠加业务判断,最后统一调用
setCustomValidity(msg) - 否则 CSS 的
:valid样式可能和实际校验状态错位
复杂表单里,:valid 只是视觉反馈的快捷入口,别让它承担逻辑责任。



















