pattern 正则验证
pattern 属性使用正则表达式对输入值进行格式验证。它为文本类型的输入控件提供了强大的格式约束能力,如手机号、身份证号、邮编等。pattern 必须与 title 属性配合使用,为用户提供验证失败时的说明。
前置知识
阅读本节前,建议先了解:required 必填验证
基础概念
什么是 pattern 验证
pattern 属性接受一个 JavaScript 正则表达式,当用户提交表单时,浏览器会检查输入值是否匹配该模式。如果不匹配,验证失败并显示 title 属性中的提示信息。
- 正则表达式:使用 JavaScript 兼容的正则语法
- 全量匹配:默认在正则两端隐式添加
^(?:...)$ - 配合 title:
title属性提供验证失败时的提示文本 - 空值不验证:如果控件值为空,pattern 不会触发验证(需要
required)
注意:隐式全量匹配
pattern 的正则表达式会自动匹配整个输入值,相当于隐式包裹 ^(?:...)$。因此不需要手动添加 ^ 和 $ 锚点:
html
<!-- 不需要 ^ 和 $,浏览器自动包裹 -->
<input pattern="[0-9]{3}-[0-9]{4}">
<!-- 实际匹配:^(?:[0-9]{3}-[0-9]{4})$ -->语法
基本用法
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>pattern 基本示例</title>
</head>
<body>
<h2>手机号验证</h2>
<form>
<label for="phone">手机号码:</label>
<input
type="tel"
id="phone"
name="phone"
pattern="1[3-9]\d{9}"
title="请输入 11 位手机号,以 1 开头,第二位为 3-9"
required
placeholder="13800138000"
>
<button type="submit">提交</button>
</form>
</body>
</html>pattern 与 title 配合
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>pattern + title</title>
</head>
<body>
<h2>邮编验证</h2>
<form>
<label for="zipcode">邮政编码:</label>
<input
type="text"
id="zipcode"
name="zipcode"
pattern="\d{6}"
title="请输入 6 位数字邮政编码"
required
placeholder="100000"
>
<button type="submit">提交</button>
</form>
<p>验证失败时,浏览器会显示 title 中的提示文字。</p>
</body>
</html>详细说明
常用 pattern 示例
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>常用 pattern</title>
<style>
body { font-family: sans-serif; max-width: 700px; margin: 40px auto; }
.form-group { margin-bottom: 12px; }
label { display: block; margin-bottom: 4px; font-weight: 600; }
input {
padding: 8px 12px;
border: 2px solid #ddd;
border-radius: 6px;
width: 300px;
}
table { border-collapse: collapse; width: 100%; margin-top: 16px; }
th, td { padding: 8px; text-align: left; border: 1px solid #ddd; }
code { background: #f5f5f5; padding: 2px 6px; border-radius: 3px; font-size: 13px; }
</style>
</head>
<body>
<h2>常用 pattern 模式</h2>
<form>
<div class="form-group">
<label for="cn-phone">中国手机号:</label>
<input type="tel" id="cn-phone" pattern="1[3-9]\d{9}"
title="11位手机号,1开头,第二位3-9" placeholder="13800138000">
</div>
<div class="form-group">
<label for="cn-zip">中国邮编:</label>
<input type="text" id="cn-zip" pattern="\d{6}"
title="6位数字邮政编码" placeholder="100000">
</div>
<div class="form-group">
<label for="cn-id">身份证号(18位):</label>
<input type="text" id="cn-id" pattern="\d{17}[\dXx]"
title="18位身份证号" placeholder="110101199001011234">
</div>
<div class="form-group">
<label for="username">用户名(字母数字下划线):</label>
<input type="text" id="username" pattern="[a-zA-Z0-9_]{3,20}"
title="3-20位字母、数字或下划线" placeholder="user_01">
</div>
<div class="form-group">
<label for="hex-color">十六进制颜色:</label>
<input type="text" id="hex-color" pattern="#[0-9a-fA-F]{6}"
title="6位十六进制颜色值" placeholder="#4a90d9">
</div>
<div class="form-group">
<label for="ip">IPv4 地址:</label>
<input type="text" id="ip"
pattern="((25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)\.){3}(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)"
title="IPv4 格式" placeholder="192.168.1.1">
</div>
<div class="form-group">
<label for="no-space">不允许空格:</label>
<input type="text" id="no-space" pattern="\S+"
title="不能包含空格" placeholder="无空格文本">
</div>
</form>
<h3>常用 pattern 速查表</h3>
<table>
<tr><th>场景</th><th>pattern</th><th>说明</th></tr>
<tr><td>中国手机号</td><td><code>1[3-9]\d{9}</code></td><td>11位,1开头</td></tr>
<tr><td>邮编</td><td><code>\d{6}</code></td><td>6位数字</td></tr>
<tr><td>身份证</td><td><code>\d{17}[\dXx]</code></td><td>18位</td></tr>
<tr><td>用户名</td><td><code>[a-zA-Z0-9_]{3,20}</code></td><td>字母数字下划线</td></tr>
<tr><td>大写字母</td><td><code>[A-Z]+</code></td><td>纯大写</td></tr>
<tr><td>十六进制颜色</td><td><code>#[0-9a-fA-F]{6}</code></td><td>#rrggbb</td></tr>
<tr><td>无空格</td><td><code>\S+</code></td><td>非空白字符</td></tr>
</table>
</body>
</html>空值不触发 pattern 验证
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>pattern 空值行为</title>
</head>
<body>
<h2>pattern 与空值</h2>
<form>
<p>以下手机号字段有 pattern 但没有 required:</p>
<label for="phone">手机号(选填):</label>
<input type="tel" id="phone" name="phone"
pattern="1[3-9]\d{9}" title="请输入有效手机号">
<button type="submit">提交</button>
</form>
<p>用户可以留空提交(pattern 不会验证空值)。</p>
<p>如果要求必须填写且格式正确,需要同时添加 <code>required</code>:</p>
<form>
<label for="phone2">手机号(必填):</label>
<input type="tel" id="phone2" name="phone2"
pattern="1[3-9]\d{9}" title="请输入有效手机号" required>
<button type="submit">提交</button>
</form>
</body>
</html>JavaScript 动态设置 pattern
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>动态 pattern</title>
</head>
<body>
<h2>动态验证规则</h2>
<form id="dynamic-form">
<div>
<label for="input-type">验证类型:</label>
<select id="input-type">
<option value="phone">手机号</option>
<option value="email">邮箱</option>
<option value="zip">邮编</option>
<option value="none">无验证</option>
</select>
</div>
<div>
<label for="input-value">输入值:</label>
<input type="text" id="input-value" name="value" placeholder="根据上方类型输入">
</div>
<button type="submit">验证</button>
</form>
<p id="result"></p>
<script>
const patterns = {
phone: { pattern: '1[3-9]\\d{9}', title: '请输入11位手机号' },
email: { pattern: '[^@]+@[^@]+\\.[^@]+', title: '请输入有效邮箱' },
zip: { pattern: '\\d{6}', title: '请输入6位邮编' },
none: { pattern: '', title: '' }
};
const typeSelect = document.getElementById('input-type');
const input = document.getElementById('input-value');
typeSelect.addEventListener('change', function () {
const rule = patterns[this.value];
if (rule.pattern) {
input.pattern = rule.pattern;
input.title = rule.title;
input.placeholder = `格式:${rule.title}`;
} else {
input.removeAttribute('pattern');
input.removeAttribute('title');
input.placeholder = '无需特定格式';
}
});
</script>
</body>
</html>实战示例
多字段格式验证
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>多字段 pattern 验证</title>
<style>
body { font-family: sans-serif; max-width: 600px; margin: 40px auto; }
.form-group { margin-bottom: 16px; }
label { display: block; margin-bottom: 4px; font-weight: 600; }
input {
width: 100%;
padding: 8px 12px;
border: 2px solid #ddd;
border-radius: 6px;
box-sizing: border-box;
}
input:valid { border-color: #27ae60; }
input:invalid:not(:focus):not(:placeholder-shown) { border-color: #e74c3c; }
.hint { font-size: 13px; color: #666; margin-top: 2px; }
button {
padding: 10px 24px;
background: #4a90d9;
color: #fff;
border: none;
border-radius: 6px;
cursor: pointer;
}
</style>
</head>
<body>
<h2>信息验证</h2>
<form id="verify-form">
<div class="form-group">
<label for="name">用户名:</label>
<input type="text" id="name" name="name"
pattern="[a-zA-Z0-9\u4e00-\u9fa5_]{2,16}"
title="2-16位中英文、数字或下划线"
required placeholder="用户名">
<p class="hint">2-16位中英文、数字或下划线</p>
</div>
<div class="form-group">
<label for="phone">手机号:</label>
<input type="tel" id="phone" name="phone"
pattern="1[3-9]\d{9}"
title="请输入11位手机号"
required placeholder="13800138000">
<p class="hint">11位手机号</p>
</div>
<div class="form-group">
<label for="invite-code">邀请码:</label>
<input type="text" id="invite-code" name="invite_code"
pattern="[A-Z]{2}-\d{4}"
title="格式:XX-0000(2大写字母-4数字)"
placeholder="AB-1234">
<p class="hint">格式:XX-0000</p>
</div>
<button type="submit">提交验证</button>
</form>
<script>
document.getElementById('verify-form').addEventListener('submit', function (e) {
e.preventDefault();
if (this.checkValidity()) {
alert('验证通过!');
} else {
this.reportValidity();
}
});
</script>
</body>
</html>注意事项
pattern 不适用于所有类型
pattern 仅适用于基于文本的输入类型(text、search、tel、url、email、password)。对 number、date、range 等类型无效。
正则中的反斜杠需要双重转义
在 HTML 属性中,反斜杠需要双重转义:
html
<!-- HTML 属性中的正则 -->
<input pattern="\\d{6}">
<!-- JavaScript 中的正则 -->
<input pattern="\d{6}">空值通过 pattern 验证
如果用户未输入任何值(空字符串),pattern 不会触发验证。需要搭配 required 强制填写。
最佳实践
- 始终配合 title:为 pattern 提供清晰的错误说明
- 提供格式提示:在 placeholder 或说明文字中展示正确格式
- 正则简洁实用:不要过度复杂的正则,兼顾可读性和实用性
- 结合 required:需要必填的字段同时添加
required - 服务端二次验证:客户端验证可绕过,服务端必须再次校验
- 测试正则:在浏览器中充分测试正则的正确性
下一节
继续学习:min / max / step