formnovalidate仅对type="submit"按钮生效,用于局部跳过表单校验;它不接受值,优先级高于novalidate,但低版本浏览器不支持,需JS兜底。

formnovalidate只能加在type="submit"按钮上
它不是通用属性,加在 input、div 或普通 button(没设 type="submit")上完全无效。浏览器只认:提交按钮 + formnovalidate 这个组合。
常见错误写法:<button formnovalidate>保存</button> ❌ 缺少 type="submit",照样触发校验;正确写法必须是:<button type="submit" formnovalidate>保存草稿</button>
- 如果表单有多个
button[type="submit"],只有带formnovalidate的那个跳过校验 - 该属性不接受值,
formnovalidate="false"或formnovalidate=""都等同于启用——只要存在就生效 - 它不影响其他按钮,也不影响
form.noValidate = true等全局设置,二者可共存
formnovalidate和novalidate同时存在时谁生效
formnovalidate 优先级更高:哪怕整个表单已加了 novalidate,某个按钮仍可单独“恢复”校验(只要不加 formnovalidate);反过来,如果表单没加 novalidate,但某按钮加了 formnovalidate,就只对那个按钮生效。
也就是说:formnovalidate 是“局部豁免”,novalidate 是“全局静音”,它们互不干扰,可以混用。
- 场景举例:一个订单表单含“暂存”“预览”“提交”三个按钮,“暂存”和“预览”加
formnovalidate,“提交”不加 → 前两者跳过校验,后者仍走原生验证流程 - 注意:若按钮用
formaction指向不同 endpoint,formnovalidate依然只控制校验,不影响提交地址
点击formnovalidate按钮后,checkValidity()还准不准
准。加了 formnovalidate 只是让浏览器在点击那一刻跳过校验拦截,但所有 DOM API 不受影响:form.checkValidity()、input.validity.valid、input.reportValidity() 全部照常工作。
这意味着你可以用它做“无感提交+手动校验”:比如点击“暂存”时先调用 form.checkValidity() 判断状态,再决定是否发请求或提示用户。
- 别依赖“没弹窗=校验通过”——
formnovalidate后用户可能填了非法邮箱,input.validity.typeMismatch仍是true - 如果想彻底屏蔽某字段校验,得删掉它的
required、pattern等属性,或设input.disabled = true -
form.submit()调用也跳过校验,但它不触发submit事件,无法用 JS 拦截或记录日志
formnovalidate在低版本浏览器里靠不住
IE10–11 和 Android 4.4 原生 WebView 完全不支持 formnovalidate,点击带该属性的按钮仍会触发校验。这时候必须用 JS 补救:
监听按钮 click,第一时间 event.preventDefault(),再手动调用 form.submit();或者更稳妥地,统一用 JS 提交,把校验逻辑收口到代码里。
- 兼容写法示例:
document.querySelector('button[data-action="draft"]').addEventListener('click', e => { e.preventDefault(); form.submit(); }); - 别指望 CSS 伪类(如
:invalid)在禁用后还能反映真实状态——formnovalidate不改变字段 validity,但浏览器不会自动重绘伪类样式 - 真正容易被忽略的是:加了
formnovalidate后,用户可能误以为“这个按钮不需要填全”,结果后端收到空数据。所以“暂存”类操作最好仍做最小化校验(比如至少要传formId),别完全放行

















