required属性仅对input(text/email/number等)、select、textarea生效,提交时校验空值但空格视为已填,服务端必须二次校验。

required 属性加在 <input>、<select> 或 <textarea> 上就能生效,但不是写了就拦得住提交——它只在特定类型、特定触发方式下才真正起作用。
哪些控件加了 required 才真校验
浏览器只对具备「可编辑性」和「明确空值语义」的控件做原生校验:
-
text、email、number、tel、url、password、date、textarea:空字符串""就算“没填”,校验通过 -
checkbox:必须勾选,否则报错;未勾选时值为undefined,不提交 -
radio:同一name下任意一个加required,表示该组至少选一个 -
select:必须含<option value=""></option>,且不能带selected,否则默认选中即绕过 -
file:至少选一个文件才算“已填” - 以下类型加了也白加:
hidden、button、image、range、color、submit
点了提交却没提示?常见失效场景
不是属性写错了,而是校验根本没启动:
- 表单没包在
<form></form>里——required必须依附于语义化表单 - 用了
<button type="button">或没写type(默认是button),不是submit - 在
submit事件里写了e.preventDefault(),但没手动调form.checkValidity() - 用 JS 直接调
form.submit()—— 这个调用完全跳过原生校验 - 字段被设为
disabled:直接忽略required;readonly仍参与校验 - iOS Safari ≤15.4 对
type="file"和type="select"的required支持不稳定
怎么让 required 行为更可控
浏览器默认提示文案不可改、样式不可控,但能有限干预:
立即学习“前端免费学习笔记(深入)”;
- 用
setCustomValidity()替换提示:输入为空时调el.setCustomValidity('此项不能为空'),非空时**必须立刻**调el.setCustomValidity('')清空,否则后续校验失效 -
:invalid伪类一加载就生效,容易误标;推荐用input:invalid:not(:placeholder-shown)延迟反馈 - 失焦即校验需手动触发:
input.addEventListener('blur', () => el.reportValidity()),它会弹气泡并返回布尔值 -
aria-required="true"只供读屏器识别,不触发校验,建议和required共存 - 空格字符串
" "被判为“已填”,required不处理 trim;服务端永远要二次校验
最常被忽略的是:用户禁用 JS、用 curl 提交、或绕过 HTML 直接发请求,都能跳过 required。它只是体验层第一道防线,不是安全机制。



















