input:required:invalid 是必填未填的黄金选择器,因 :required 筛选必填元素,:invalid 判定无效状态,二者交集才精准标识“本该填、还没填、浏览器已判无效”。

required 是 HTML 属性,:invalid 是浏览器自动计算出的状态伪类,二者配合才能实现“该填未填”的精准样式控制;单独用 :invalid 会误标所有无约束的空字段,而只写 required 又无法触发视觉反馈。
为什么 input:required:invalid 才是必填未填的黄金选择器
页面加载后,一个带 required 的空 <input> 立刻匹配 :required:invalid,但不会匹配 :invalid 单独存在的情况(除非它还有 type="email" 或 pattern 等其他约束)。这能避免把非必填字段(比如可选的“公司网址”)也标红。
-
:required只筛选出“声明为必填”的元素,不关心值是否为空 -
:invalid只反映“当前值违反任一验证规则”,哪怕字段没设required - 只有两者交集,才真正代表「本该填、还没填、浏览器已判定无效」
-
select:required:invalid要求默认<option></option>没有value(如<option disabled selected>请选择</option>),否则会被当成有效值绕过校验
如何避免页面一打开就满屏红框
直接写 input:invalid { border: 2px solid red; } 会导致所有空 required 字段在加载完成瞬间就变红——用户还没点进去,就被错误提示包围。这不是 bug,是 :invalid 的设计行为。
- 最轻量解法:加
placeholder,用input:invalid:not(:placeholder-shown)—— 只有用户输过又删空,或输入非法内容时才触发 - 注意:
type="number"和type="date"不支持placeholder,得换方案,比如监听:focus-within或用 JS 切换临时 class - 更现代的替代:
:user-invalid(Chrome 107+ / Firefox 119+ 支持),仅在用户与该字段发生交互后才激活:invalid状态 - 别依赖
:valid做初始隐藏,因为空字段对大多数类型来说既不:valid也不:invalid(除非有required)
checkValidity() 和 invalid 事件怎么配合 CSS 用
CSS 的 :invalid 只负责“看起来错”,JS 的 checkValidity() 和 invalid 事件负责“阻止提交”和“自定义提示”。它们不是互斥的,而是分工明确。
-
form.checkValidity()返回false表示至少一个字段未通过校验,常用于submit事件中e.preventDefault() -
input.addEventListener('invalid', e => { e.preventDefault(); })可拦截浏览器默认弹窗,换成 tooltip 或 aria-live 提示 - 注意:
invalid事件在浏览器判定字段无效时立即触发(比如失去焦点、输入非法字符),不是等表单提交才发生 - 如果用 JS 动态改了
input.value,记得手动调input.reportValidity()来强制重触:invalid状态
移动端和无障碍要注意的细节
原生验证在移动端表现差异大,且屏幕阅读器对 :invalid 的感知依赖于 aria-invalid 属性是否同步更新。
-
required在 iOS Safari 中可能不触发数字键盘,建议搭配inputmode="numeric"显式声明 -
:invalid样式本身不被屏幕阅读器朗读,必须手动设置aria-invalid="true"并配aria-describedby指向错误文案 -
type="checkbox"和type="radio"的:invalid触发逻辑不同:未勾选的requiredcheckbox 加载即:invalid;radio 组需至少一个被选中,否则整个组都算:invalid - 不要用
display: none隐藏错误提示,它会让屏幕阅读器跳过;改用visibility: hidden或clip-path+aria-hidden
真正难的不是写对 input:required:invalid,而是让它的触发时机、颜色反馈、JS 拦截、无障碍提示全部对齐同一套用户心智模型——稍有错位,就会出现“我明明填了却还报错”或“我根本没看到哪里错了”这类问题。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











