pattern仅对text、tel、email等字符串型type生效,number等类型因转为数值而忽略pattern;需用type="text"+inputmode="numeric"或type="tel"保留字符串语义;正则无需^$,title是唯一提示出口,须明确描述格式要求。

pattern 属性只对特定 type 生效
浏览器会直接忽略 pattern 在 number、date、range、checkbox 等 type 上的设置——因为这些类型在解析时已转为数值或布尔,原始字符串根本没传给正则引擎。
常见踩坑写法:<input type="number" pattern="[0-9]{6}"> 永远不触发校验;iOS 下还可能自动删前导零,导致用户输入 001234 变成 1234。
- ✅ 正确做法:用
type="text"+inputmode="numeric"保留字符串语义,同时唤起数字键盘 - ✅ 手机号校验必须用
type="tel",它既保留字符串又支持 pattern - ✅ 邮箱、URL、密码等语义明确的字段,优先用对应
type,再补pattern做细化约束
正则写法必须适配 HTML5 的隐式锚点机制
HTML5 的 pattern 自动包裹为 ^(?:...)$,你写的正则只是中间部分。显式加 ^ 或 $ 不但冗余,旧版 Safari 还可能跳过整条规则。
MAC 地址校验是个典型例子:pattern="([0-9A-Fa-f]{2}[:-]){5}[0-9A-Fa-f]{2}" 是安全写法;而 pattern="^([0-9A-Fa-f]{2}[:-]){5}[0-9A-Fa-f]{2}$" 在部分环境会失效。
立即学习“前端免费学习笔记(深入)”;
- ❌
pattern="/^[a-z]+$/i":斜杠和修饰符被当作文本字面匹配,永远失败 - ❌
pattern="d{8}":缺少反斜杠,实际匹配的是字母d而非数字 - ✅ 所有字符组里的
-必须转义或放末尾,如[:\-]或[^-],否则被解析为范围符
title 是唯一可控的提示出口,不设就等于没写 pattern
没设 title,Chrome/Firefox 默认报错文案是“请与所要求的格式匹配”,用户完全不知道要输什么。而 title 是唯一能在错误气泡、hover 提示、input.validationMessage 中复用的内容。
iOS Safari 对 title 支持较弱,若需强提示,得用 JS 的 setCustomValidity() 补充;但注意:每次 input 事件里必须调用 setCustomValidity('') 清空,否则错误状态会滞留。
- ✅
title="请输入6位纯数字,不要加空格或字母"比title="格式错误"有用十倍 - ✅
title可写中文、emoji、标点,无需 URL 编码 - ✅ 它不参与校验逻辑,只用于展示,所以可自由发挥表达力
冲突本质是验证时机与事件链错位
原生验证只在 submit、checkValidity() 或用户交互(如 blur)时触发;而 JS 监听 input 或 blur 并手动调用 setCustomValidity(),若未同步清空或未阻止默认行为,就会出现双提示、样式残留、提交被静默放过等问题。
最常被忽略的是:即使写了 novalidate,浏览器仍会设置 :invalid 伪类,CSS 里如果写了 input:invalid { border: 1px solid red; },视觉上就像“还在校验”。
- 监听
invalid事件时,必须调用event.preventDefault()阻止默认提交,否则表单可能意外通过 -
formnovalidate只对单次提交有效,真要禁用全部校验,起点必须是<form novalidate> - 第三方库(如 VeeValidate、Formik)和原生
required共存时,容易互相干扰,建议统一用一套方案
pattern,也不会主动暴露 invalid 事件是否被拦截——这些细节一旦漏掉,验证就变成“看起来在跑,其实没生效”。



















