required属性是最简必填校验方案,兼容ie10+,需配合:invalid/:user-invalid css高亮,动态表单中需延迟查询伪类以确保生效。

用 required 属性最简实现必填校验
浏览器原生支持表单必填校验,required 是最轻量、兼容性最好(IE10+)的方案。它不依赖 JS,提交时自动拦截并提示用户补全,且会触发伪类 :invalid,便于 CSS 高亮。
常见错误是只加 required 却没配样式,导致用户只看到默认浏览器弹窗(体验差),或根本没感知字段异常。必须配合 CSS 控制视觉反馈。
-
<input type="text" name="name" required>即可标记为必填,无需 JS 干预 - 提交前不填时,该元素会自动拥有
:invalid状态(即使值为空字符串或未聚焦) - 注意:若元素有
value初始值(哪怕为空格),:invalid可能不触发,建议清空初始value
用 :invalid 和 :user-invalid 区分高亮时机
:invalid 在表单加载后立即生效,可能导致“未操作就红边”,干扰用户;:user-invalid(Chrome 95+、Firefox 93+、Safari 16.4+)仅在用户交互后(如失焦、输入再删除)才激活,更符合直觉。
实操建议优先用 :user-invalid,降级兜底 :invalid:
input:invalid:not(:placeholder-shown) {
border-color: #e53e3e;
}
input:user-invalid {
border-color: #e53e3e;
}
-
:not(:placeholder-shown)排除 placeholder 显示时的误判(避免 placeholder 存在时一加载就红) - 旧浏览器不支持
:user-invalid,所以保留:invalid规则作为 fallback - 不要只写
input:invalid,否则 placeholder 存在时也会触发,造成误高亮
JS 主动触发校验并高亮(绕过 submit 拦截)
有些场景不能靠原生 submit(比如用 AJAX 提交、或按钮绑定 click 事件),此时需手动调用 checkValidity() 并遍历高亮无效字段。
关键点:不能只靠 reportValidity()(它只弹提示),要结合 DOM 操作显式标记:
function highlightInvalidFields(form) {
const invalids = form.querySelectorAll(':invalid');
invalids.forEach(el => el.classList.add('invalid'));
return form.checkValidity();
}
-
form.checkValidity()返回布尔值,不弹窗,适合静默校验 -
form.reportValidity()会触发浏览器默认提示,但无法控制样式,慎用 - 务必在调用前确保元素已渲染完成,动态插入的表单项需等 DOM 更新后再查
:invalid - 注意:Vue/React 中直接用
:invalid伪类可能因虚拟 DOM 渲染时机失效,建议改用 JS 维护invalidclass
隐藏原生报错气泡(title 或 setCustomValidity)
默认提交失败时,Chrome 会在字段旁显示“请填写此字段”气泡,文字不可控、位置固定、无法关闭。想统一用自定义提示,得主动抑制它。
两种可靠方式:
- 给所有必填字段加空
title="",可屏蔽部分浏览器的默认提示(但非 100% 有效) - 更稳妥的是在聚焦时重置校验:
el.setCustomValidity(''),并在失焦时按逻辑设错:el.setCustomValidity('此项必填') - 注意:
setCustomValidity('')不等于清除校验,而是表示“通过”,需搭配 JS 逻辑使用 - 一旦用了
setCustomValidity,原生required校验会被覆盖,必须自行判断空值
:user-invalid 的兼容性边界和动态表单中伪类查询时机——DOM 插入后立即 querySelectorAll(':invalid') 可能返回空列表,得用 setTimeout 或 requestAnimationFrame 延迟执行。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











