表单验证伪类需原生属性触发,:invalid/:valid 依赖 required 等约束;:user-invalid 更符合提交后反馈逻辑;空值处理存在浏览器差异;JS 需配合 checkValidity() 和 class 控制确保状态准确。

表单验证状态没生效?检查 :invalid 和 :valid 的触发条件
这两个伪类只对「原生表单验证属性生效」,比如 required、type="email"、pattern,不是随便加个 input 就能响应的。没写验证属性,或者用了 JS 手动设置 setCustomValidity 但没调用 reportValidity(),伪类就完全不触发。
- 必须有
required或其他验证约束,否则浏览器认为字段“无约束”,始终为:valid -
type="text"不会校验格式,哪怕输入邮箱也不会变:valid;换成type="email"才会按邮箱规则判断 - 动态修改
value后,伪类不会自动更新——得靠用户交互(如失焦)或手动触发checkValidity()
提交后才想高亮错误?得靠 :user-invalid,不是 :invalid
:invalid 在输入过程中就可能激活,而用户真正关心的是「提交失败后」的反馈。Chrome 102+、Firefox 119+ 支持 :user-invalid,它只在用户与该字段交互过(focus → blur)且验证失败时才匹配,更符合“提交后样式”的直觉。
- 旧版浏览器不支持
:user-invalid,需降级回:invalid+ JS 添加临时 class(如submitted)来模拟 - 不要只依赖
:invalid做提交后样式,否则用户还没输就看到红框,体验突兀 - 示例:提交按钮点击后,给整个
form加data-submitted属性,CSS 写form[data-submitted] input:invalid
为什么加了 :valid 样式却没变绿?注意初始状态和空值处理
空的 required 输入框默认是 :invalid,但一旦用户输入又删空,部分浏览器(如 Safari)会卡在 :valid 状态,导致样式异常。这不是 bug,而是规范允许的「空值视为通过验证」行为(只要没违反 pattern 等显式规则)。
-
required字段为空时,:invalid必然生效;但清空后是否保持:invalid,取决于浏览器实现 - 若需严格控制「空即无效」,可用
pattern=".+"强制非空,此时空值会触发:invalid - 避免用
:valid控制成功提示(如绿色边框),优先用:user-valid(同:user-invalid,新标准)或 JS 控制
联动 JS 时,别直接监听 submit 事件改样式
表单提交被取消(如 event.preventDefault())后,浏览器不会重置验证状态,:invalid 仍保留,但用户可能已修正内容。这时仅靠伪类无法反映最新状态,必须配合 JS 主动刷新。
- 在
submit事件里调用form.checkValidity(),再根据结果添加/移除 class,比纯 CSS 更可控 - 不要用
form.addEventListener('invalid', ...)—— 这个事件不冒泡,且只在原生验证失败时触发,JS 设置的错误不触发它 - 兼容性兜底建议:给
input绑定blur和input,用checkValidity()更新 class,再让 CSS 基于 class 而非伪类驱动样式
实际项目里最常漏掉的是 :user-invalid 的渐进增强逻辑,以及清空输入后验证状态的浏览器差异。这些点不手动测一遍,光看文档很容易以为样式“应该生效”。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











