tel 电话输入
type="tel" 是 HTML5 为电话号码设计的输入控件。与 type="email" 和 type="number" 不同,type="tel" 不会自动验证输入格式——因为全球的电话号码格式差异极大,浏览器无法定义通用的验证规则。它的主要价值在于移动端键盘优化,以及在语义上标识该字段的用途。
前置知识
阅读本节前,建议先了解:number 数字输入
基础概念
什么是 tel 输入
type="tel" 创建一个用于输入电话号码的输入框。它的核心特点:
- 不自动验证:浏览器不会检查输入是否为有效的电话号码
- 移动端键盘优化:在手机上弹出电话拨号键盘(数字 +
*#) - 语义化:屏幕阅读器会识别这是一个电话号码输入框
- 支持 pattern 验证:通过
pattern属性实现自定义格式验证
<!-- 基本 tel 输入 -->
<input type="tel" name="phone" placeholder="13800138000">
<!-- 不自动验证,以下都能通过提交 -->
<!-- 13800138000 有效 -->
<!-- abcdefgh 有效(浏览器不验证) -->
<!-- 123 有效 -->tel 的核心特征
| 特征 | 说明 |
|---|---|
| 输入方式 | 键盘输入 |
| 数据类型 | 字符串(电话号码是字符串,不是数字) |
| 自动验证 | 无(需要 pattern 补充) |
| 移动端键盘 | 电话拨号键盘(数字 + * # + 拨打按钮) |
| 输入过滤 | 无(允许输入任意字符) |
语法
基本语法
<input
type="tel"
name="phone"
id="phone"
placeholder="13800138000"
pattern="^1[3-9]\d{9}$"
maxlength="11"
autocomplete="tel"
required
>常用属性
| 属性 | 值 | 说明 |
|---|---|---|
type | "tel" | 指定为电话输入 |
pattern | 正则表达式 | 自定义电话格式验证 |
maxlength | 正整数 | 限制输入长度 |
placeholder | 字符串 | 提示输入格式 |
autocomplete | "tel" / "tel-national" | 自动补全类型 |
详细说明
为什么 tel 不自动验证
电话号码的格式在全球范围内差异极大:
| 国家/地区 | 格式 | 示例 |
|---|---|---|
| 中国大陆 | 11位手机号 | 13800138000 |
| 美国带区号 | (XXX) XXX-XXXX | (415) 555-0132 |
| 英国 | +44 XXXX XXXXXX | +44 7911 123456 |
| 日本 | 0X0-XXXX-XXXX | 090-1234-5678 |
| 国际格式 | +国家代码 号码 | +86 138 0013 8000 |
由于这种多样性,HTML 规范不要求浏览器对 type="tel" 进行自动验证。开发者需要根据目标用户群体,使用 pattern 属性添加适当的验证规则。
使用 pattern 验证电话格式
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>tel pattern 验证</title>
<style>
.form-group { margin-bottom: 20px; }
label { display: block; font-weight: 500; margin-bottom: 6px; }
input {
width: 300px;
padding: 10px 12px;
border: 1px solid #ccc;
border-radius: 6px;
font-size: 14px;
box-sizing: border-box;
}
.hint { font-size: 13px; color: #999; margin-top: 4px; }
/* 验证样式 */
input:valid:not(:placeholder-shown) { border-color: #27ae60; }
input:invalid:not(:placeholder-shown):not(:focus) { border-color: #e74c3c; }
</style>
</head>
<body>
<h2>电话号码验证</h2>
<form action="/submit" method="post">
<!-- 中国大陆手机号(11位) -->
<div class="form-group">
<label for="mobile">中国大陆手机号</label>
<input type="tel"
id="mobile"
name="mobile"
pattern="^1[3-9]\d{9}$"
title="请输入11位中国大陆手机号"
placeholder="13800138000"
maxlength="11"
required>
<p class="hint">格式:1开头,第二位3-9,共11位数字</p>
</div>
<!-- 带区号的固定电话 -->
<div class="form-group">
<label for="landline">固定电话(带区号)</label>
<input type="tel"
id="landline"
name="landline"
pattern="^0\d{2,3}-?\d{7,8}$"
title="请输入区号-号码格式"
placeholder="010-12345678"
maxlength="13">
<p class="hint">格式:区号-号码,如 010-12345678 或 075512345678</p>
</div>
<!-- 国际电话号码 -->
<div class="form-group">
<label for="intl">国际电话</label>
<input type="tel"
id="intl"
name="intl_phone"
pattern="^\+?\d{1,3}[-\s]?\d{4,14}$"
title="请输入国际电话号码"
placeholder="+86 138 0013 8000">
<p class="hint">格式:+国家代码 号码,如 +86 138 0013 8000</p>
</div>
<!-- 宽松验证:只检查是否为数字(允许空格和横线) -->
<div class="form-group">
<label for="any">任意电话号码</label>
<input type="tel"
id="any"
name="phone"
pattern="^[\d\s\-\+\(\)]{7,20}$"
title="请输入有效的电话号码"
placeholder="任意格式的电话号码">
<p class="hint">允许包含数字、空格、横线、加号和括号</p>
</div>
<button type="submit">提交</button>
</form>
</body>
</html>移动端键盘优化
type="tel" 在移动设备上会触发电话拨号键盘,这对用户输入电话号码的体验有显著提升。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>移动端键盘对比</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<h2>移动端键盘对比</h2>
<p>在手机上打开此页面,对比不同输入框的键盘:</p>
<!--
type="text":标准全键盘
适合输入混合内容(文字+数字)
-->
<div style="margin-bottom: 20px;">
<label for="textPhone">text(标准键盘):</label><br>
<input type="text" id="textPhone" name="phone_text" placeholder="标准键盘">
</div>
<!--
type="tel":电话拨号键盘
大号数字按键 + * # + 拨打按钮
最适合输入电话号码
-->
<div style="margin-bottom: 20px;">
<label for="telPhone">tel(电话键盘):</label><br>
<input type="tel" id="telPhone" name="phone_tel" placeholder="电话键盘">
</div>
<!--
type="number":数字键盘
纯数字 + 小数点 + 正负号
不适合电话号码(缺少 * # 和拨打按钮)
-->
<div style="margin-bottom: 20px;">
<label for="numPhone">number(数字键盘,不推荐):</label><br>
<input type="number" id="numPhone" name="phone_num" placeholder="数字键盘">
<!--
不推荐使用 type="number" 输入电话号码:
1. 没有拨打按钮
2. 可能出现 spinners 箭头
3. 电话号码不是数学数字(不需要运算)
4. 可能丢失前导零(如 010 开头的区号)
-->
</div>
<!--
inputmode="tel":另一种方式
在 type="text" 上使用 inputmode="tel" 也可以触发电话键盘
适用于需要更多控制(如 pattern)的场景
-->
<div style="margin-bottom: 20px;">
<label for="inputmodePhone">text + inputmode="tel":</label><br>
<input type="text" id="inputmodePhone" name="phone_inputmode"
inputmode="tel" placeholder="也是电话键盘">
</div>
</body>
</html>不要用 type="number" 输入电话号码
虽然 type="number" 也能弹出数字键盘,但有几个问题:
- 电话号码可能包含
*(如*110#)和#等特殊字符 number类型会丢弃前导零(0755变成755)- 可能出现不必要的 spinners 箭头
- 电话号码不是用于数学计算的数字
使用 inputmode 替代方案
HTML5.1 引入了 inputmode 属性,可以在不改变 type 的情况下控制移动端键盘类型:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>inputmode 属性</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<h2>inputmode 属性</h2>
<!--
inputmode 可以与 type="text" 配合使用
在保持 text 行为的同时获得移动端键盘优化
type="tel" 等效于 type="text" + inputmode="tel"
-->
<!-- 方式一:type="tel"(推荐) -->
<input type="tel" name="phone1" placeholder="方式一:type=tel">
<!-- 方式二:type="text" + inputmode="tel"(效果相同) -->
<input type="text" name="phone2" inputmode="tel" placeholder="方式二:text+inputmode">
<!-- inputmode 的所有取值 -->
<table border="1" cellpadding="8" style="border-collapse: collapse; margin-top: 16px;">
<tr><th>inputmode 值</th><th>键盘类型</th><th>适用场景</th></tr>
<tr><td>text</td><td>标准键盘</td><td>默认值</td></tr>
<tr><td>tel</td><td>电话键盘</td><td>电话号码</td></tr>
<tr><td>email</td><td>邮箱键盘</td><td>邮箱地址</td></tr>
<tr><td>url</td><td>URL 键盘</td><td>网址</td></tr>
<tr><td>numeric</td><td>数字键盘</td><td>纯数字</td></tr>
<tr><td>decimal</td><td>带小数点的数字键盘</td><td>金额</td></tr>
<tr><td>search</td><td>搜索键盘</td><td>搜索</td></tr>
<tr><td>none</td><td>无键盘</td><td>自定义输入法</td></tr>
</table>
</body>
</html>autocomplete 优化
为电话字段设置正确的 autocomplete token,帮助浏览器和密码管理器正确保存和填充电话号码:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>tel autocomplete</title>
</head>
<body>
<form action="/profile" method="post" autocomplete="on">
<!-- 国内电话号码(无国家代码) -->
<label for="phone">手机号码:</label>
<input type="tel"
id="phone"
name="phone"
autocomplete="tel-national"
placeholder="13800138000">
<!-- 完整国际号码 -->
<label for="fullPhone">国际号码:</label>
<input type="tel"
id="fullPhone"
name="full_phone"
autocomplete="tel"
placeholder="+86 138 0013 8000">
<!-- 国家代码单独字段 -->
<label for="countryCode">国家代码:</label>
<input type="tel"
id="countryCode"
name="country_code"
autocomplete="tel-country-code"
placeholder="+86">
<button type="submit">保存</button>
</form>
</body>
</html>实战示例
带格式化的电话输入框
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>电话号码格式化</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
max-width: 500px;
margin: 40px auto;
padding: 20px;
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
font-weight: 500;
margin-bottom: 6px;
}
input {
width: 100%;
max-width: 300px;
padding: 10px 12px;
border: 1px solid #ddd;
border-radius: 6px;
box-sizing: border-box;
font-size: 16px;
letter-spacing: 1px;
}
input:focus {
outline: none;
border-color: #4a90d9;
}
.hint {
font-size: 13px;
color: #999;
margin-top: 4px;
}
.valid {
color: #27ae60;
font-size: 13px;
margin-top: 4px;
display: none;
}
.invalid {
color: #e74c3c;
font-size: 13px;
margin-top: 4px;
display: none;
}
</style>
</head>
<body>
<h2>联系信息</h2>
<form action="/api/contact" method="post">
<div class="form-group">
<label for="mobile">手机号码</label>
<input type="tel"
id="mobile"
name="mobile"
placeholder="138 0013 8000"
maxlength="13"
pattern="^1[3-9]\d{9}$"
autocomplete="tel-national"
required>
<p class="hint">11位中国大陆手机号</p>
<p class="valid" id="mobileValid">格式正确</p>
<p class="invalid" id="mobileInvalid">请输入正确的手机号</p>
</div>
</form>
<script>
const mobileInput = document.getElementById('mobile');
const validMsg = document.getElementById('mobileValid');
const invalidMsg = document.getElementById('mobileInvalid');
mobileInput.addEventListener('input', function() {
// 只保留数字
let raw = this.value.replace(/\D/g, '');
// 限制11位
if (raw.length > 11) {
raw = raw.slice(0, 11);
}
// 格式化显示:XXX XXXX XXXX
let formatted = '';
if (raw.length <= 3) {
formatted = raw;
} else if (raw.length <= 7) {
formatted = raw.slice(0, 3) + ' ' + raw.slice(3);
} else {
formatted = raw.slice(0, 3) + ' ' + raw.slice(3, 7) + ' ' + raw.slice(7);
}
this.value = formatted;
// 实时验证
const mobilePattern = /^1[3-9]\d{9}$/;
if (raw.length === 0) {
validMsg.style.display = 'none';
invalidMsg.style.display = 'none';
} else if (mobilePattern.test(raw)) {
validMsg.style.display = 'block';
invalidMsg.style.display = 'none';
} else {
validMsg.style.display = 'none';
invalidMsg.style.display = 'block';
}
});
// 提交时去除空格
mobileInput.closest('form').addEventListener('submit', function(e) {
e.preventDefault();
const raw = mobileInput.value.replace(/\s/g, '');
console.log('提交的手机号(纯数字):', raw);
});
</script>
</body>
</html>注意事项
tel 不验证输入内容:
type="tel"允许输入任何字符,不会自动检查是否为有效电话号码。必须使用pattern或 JavaScript 进行验证。电话号码是字符串不是数字:电话号码可能以
0开头(如010-12345678),可能包含*和#,不应该用type="number"输入。不要设置过严的 pattern:国际用户可能有不同格式的电话号码。如果面向全球用户,使用宽松的 pattern 或不设置 pattern,在服务器端验证。
移动端键盘差异:不同操作系统和设备的电话键盘外观可能不同,但都提供大号数字按键。
最佳实践
对国内用户使用
type="tel"+ 中国手机号 pattern:pattern="^1[3-9]\d{9}$"是常用的中国大陆手机号验证。对国际用户使用宽松的 pattern 或不验证:
pattern="^[\d\s\-\+\(\)]{7,20}$"允许大多数国际号码格式。设置
autocomplete="tel"或autocomplete="tel-national":帮助浏览器正确保存和填充电话号码。在前端格式化显示:用 JavaScript 自动添加空格或横线(如
138 0013 8000),提升可读性,但提交时发送纯数字。考虑使用专门的电话输入库:对于复杂的国际电话号码输入(需要国家代码选择器),可以考虑使用
libphonenumber-js等库。
下一节
继续学习:url 网址输入