Skip to content

tel 电话输入

type="tel" 是 HTML5 为电话号码设计的输入控件。与 type="email"type="number" 不同,type="tel" 不会自动验证输入格式——因为全球的电话号码格式差异极大,浏览器无法定义通用的验证规则。它的主要价值在于移动端键盘优化,以及在语义上标识该字段的用途。

前置知识

阅读本节前,建议先了解:number 数字输入

基础概念

什么是 tel 输入

type="tel" 创建一个用于输入电话号码的输入框。它的核心特点:

  1. 不自动验证:浏览器不会检查输入是否为有效的电话号码
  2. 移动端键盘优化:在手机上弹出电话拨号键盘(数字 + * #
  3. 语义化:屏幕阅读器会识别这是一个电话号码输入框
  4. 支持 pattern 验证:通过 pattern 属性实现自定义格式验证
html
<!-- 基本 tel 输入 -->
<input type="tel" name="phone" placeholder="13800138000">

<!-- 不自动验证,以下都能通过提交 -->
<!-- 13800138000     有效 -->
<!-- abcdefgh        有效(浏览器不验证) -->
<!-- 123             有效 -->

tel 的核心特征

特征说明
输入方式键盘输入
数据类型字符串(电话号码是字符串,不是数字)
自动验证无(需要 pattern 补充)
移动端键盘电话拨号键盘(数字 + * # + 拨打按钮)
输入过滤无(允许输入任意字符)

语法

基本语法

html
<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-XXXX090-1234-5678
国际格式+国家代码 号码+86 138 0013 8000

由于这种多样性,HTML 规范不要求浏览器对 type="tel" 进行自动验证。开发者需要根据目标用户群体,使用 pattern 属性添加适当的验证规则。

使用 pattern 验证电话格式

html
<!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" 在移动设备上会触发电话拨号键盘,这对用户输入电话号码的体验有显著提升。

html
<!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" 也能弹出数字键盘,但有几个问题:

  1. 电话号码可能包含 *(如 *110#)和 # 等特殊字符
  2. number 类型会丢弃前导零(0755 变成 755
  3. 可能出现不必要的 spinners 箭头
  4. 电话号码不是用于数学计算的数字

使用 inputmode 替代方案

HTML5.1 引入了 inputmode 属性,可以在不改变 type 的情况下控制移动端键盘类型:

html
<!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,帮助浏览器和密码管理器正确保存和填充电话号码:

html
<!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>

实战示例

带格式化的电话输入框

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>

注意事项

  1. tel 不验证输入内容type="tel" 允许输入任何字符,不会自动检查是否为有效电话号码。必须使用 pattern 或 JavaScript 进行验证。

  2. 电话号码是字符串不是数字:电话号码可能以 0 开头(如 010-12345678),可能包含 *#,不应该用 type="number" 输入。

  3. 不要设置过严的 pattern:国际用户可能有不同格式的电话号码。如果面向全球用户,使用宽松的 pattern 或不设置 pattern,在服务器端验证。

  4. 移动端键盘差异:不同操作系统和设备的电话键盘外观可能不同,但都提供大号数字按键。

最佳实践

  1. 对国内用户使用 type="tel" + 中国手机号 patternpattern="^1[3-9]\d{9}$" 是常用的中国大陆手机号验证。

  2. 对国际用户使用宽松的 pattern 或不验证pattern="^[\d\s\-\+\(\)]{7,20}$" 允许大多数国际号码格式。

  3. 设置 autocomplete="tel"autocomplete="tel-national":帮助浏览器正确保存和填充电话号码。

  4. 在前端格式化显示:用 JavaScript 自动添加空格或横线(如 138 0013 8000),提升可读性,但提交时发送纯数字。

  5. 考虑使用专门的电话输入库:对于复杂的国际电话号码输入(需要国家代码选择器),可以考虑使用 libphonenumber-js 等库。

下一节

继续学习:url 网址输入

参考链接