Skip to content

表单增强

作者:Annan
发表于:2025-05-01
更新于:几秒前
字数统计:1.5k 字
阅读时长:6 分钟
阅读量:

HTML5 对表单的增强极大提升了表单的可用性、可访问性和用户体验。主要增强点如下:

1. 新的表单控件类型

类型说明
type="email"邮箱格式校验
type="url"网址格式校验
type="tel"电话输入
type="number"数字输入,可设置 min/max/step
type="range"滑块选择
type="date"日期选择器
type="month"月份选择器
type="week"周选择器
type="time"时间选择器
type="datetime-local"本地日期时间选择器
type="color"颜色选择器
type="search"搜索输入框
type="file"文件上传,支持 multiple 多文件

2. 新的属性和特性

  • required:必填项
  • placeholder:输入提示
  • pattern:正则表达式校验
  • minmaxstep:数值和日期范围限制
  • autofocus:自动聚焦
  • autocomplete:自动补全
  • multiple:允许多值输入(如 email、file、select)
  • readonlydisabled:只读/禁用状态
  • form:允许表单控件在表单外部,通过 form 属性指定归属的表单
  • novalidate:表单提交时不进行校验

3. 新的表单元素

标签作用说明
<datalist><input> 提供下拉建议列表
<output>用于显示计算或脚本输出
<progress>进度条
<meter>刻度值条(如分数、温度等)

4. 原生表单校验

  • 浏览器自动校验格式(如邮箱、URL、数字范围、正则等),无需 JS 代码
  • 校验不通过时自动阻止提交,并提示用户

5. 表单相关的 JS API 增强

  • 新增了 checkValidity()setCustomValidity() 等方法,便于自定义和触发校验
  • 可以通过 JS 访问 validity 状态、validationMessage

6. 可访问性和移动端体验提升

  • 新类型输入框在移动端会弹出合适的键盘(如数字、邮箱、日期等)
  • 更好地支持屏幕阅读器和辅助技术

7. 总览表格

类型/标签/属性作用/增强点
新 input 类型email, url, number, date 等
新标签datalist, output, progress, meter
新属性required, pattern, min, max, step, multiple, autofocus, autocomplete, placeholder, form
原生校验格式、范围、正则、必填等
JS APIcheckValidity, setCustomValidity
移动端体验弹出合适键盘,易输入

8. 实践示例

html
<!DOCTYPE html>
<html lang="zh-CN">

<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>通用HTML模板</title>
  <!-- 样式占位,可自定义CSS -->
  <style>
    body {
      font-family: Arial, Helvetica, sans-serif;
      margin: 0;
      padding: 0;
      background: #f8f9fa;
      color: #222;
    }

    main {
      max-width: 900px;
      margin: 2rem auto;
      background: #fff;
      padding: 2rem;
      border-radius: 8px;
      box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
    }

    nav {
      margin-bottom: 1.5rem;
    }

    a {
      color: #007bff;
      text-decoration: none;
    }

    a:hover {
      text-decoration: underline;
    }
  </style>
</head>

<body>
  <main>
    <h2>表单示例</h2>
    <form>
      <div style="margin-bottom: 1em">
        <label for="color">颜色选择:</label>
        <input id="color" name="color" type="color" />
      </div>
      <div style="margin-bottom: 1em">
        <label for="date">日期:</label>
        <input id="date" name="date" type="date" />
        <label for="datetime">日期时间:</label>
        <input id="datetime" name="datetime" type="datetime-local" />
        <label for="month">月份:</label>
        <input id="month" name="month" type="month" />
        <label for="week">周:</label>
        <input id="week" name="week" type="week" />
        <label for="time">时间:</label>
        <input id="time" name="time" type="time" />
      </div>
      <div style="margin-bottom: 1em">
        <label for="number">数字:</label>
        <input id="number" placeholder="值为0~10之间" step="0.5" required name="number" type="number" min="0" max="10"
          style="width: 100px;" />
        <span style="font-size: 12px; color: #888">number</span>
      </div>
      <div style="margin-bottom: 1em">
        <label for="email">邮箱:</label>
        <input id="email" name="email" type="email" required />
        <span style="font-size: 12px; color: #888">email 在提交时才会校验邮箱</span>
      </div>
      <div style="margin-bottom: 1em">
        <label for="tel">手机号:</label>
        <input id="tel" name="tel" type="tel" />
        <span style="font-size: 12px; color: #888">tel 没有格式校验,主要是移动端弹出数字键盘</span>
      </div>
      <div style="margin-bottom: 1em">
        <label for="search">搜索:</label>
        <input id="search" name="search" type="search" autofocus />
        <span style="font-size: 12px; color: #888">search
          浏览器会有清除按钮,利于SEO和可访问性,移动端弹出键盘的确认会变成搜索</span>
      </div>
      <div style="margin-bottom: 1em">
        <label for="range">范围:</label>
        <input id="range" name="range" type="range" />
      </div>
      <div style="margin-bottom: 1em">
        <label for="custom">自定义验证:</label>
        <input id="custom" name="custom" type="text" />
        <span id="custom-error" style="color: red; font-size: 12px;"></span>
      </div>
      <span style="font-size: 12px; color: #888">range</span>
      </div>
      <div style="margin-bottom: 1em">
        <label for="file">多文件上传:</label>
        <input id="file" name="file" type="file" multiple />
        <span style="font-size: 12px; color: #888">multiple 支持多文件上传</span>
      </div>
      <div style="margin-bottom: 1em">
        <label>height/width image</label>
        <input type="image" name="" value="" width="100" height="100">
      </div>
      <!-- <button type="submit" style="padding: 0.5em 1.5em">提交</button> -->
      <section style="margin-top:2em;">
        <div style="margin-bottom:1em;">
          <details>
            <summary>&lt;details&gt; 下拉详情演示</summary>
            用户会在他们输入数据时看到域定义选项的下拉列表。
            <br />
            例如:
            <input list="browsers" name="browser">
            <datalist id="browsers">
              <option value="Chrome">
              <option value="Firefox">
              <option value="Safari">
              <option value="Edge">
            </datalist>
          </details>
        </div>
        <div style="margin-bottom:1em;">
          <label for="progress-demo">&lt;progress&gt; 进度条:</label>
          <progress id="progress-demo" value="0.6" max="1" style="width:200px;"></progress>
          <span style="font-size:12px;color:#888;">展示连接/下载进度</span>
        </div>
        <div style="margin-bottom:1em;">
          <label for="meter-demo">&lt;meter&gt; 刻度值:</label>
          <meter id="meter-demo" min="0" max="100" value="70" low="40" high="90" optimum="80"
            style="width:200px;"></meter>
          <span style="font-size:12px;color:#888;">用于计量(如温度、权重、分数等)</span>
        </div>
        <div style="margin-bottom:1em;">
          <label for="output-demo">&lt;output&gt; 输出:</label>
          <span style="font-size:12px;color:#888;">用于不同类型的输出,比如计算或脚本输出</span>
        </div>
      </section>
      <button type="submit" onclick="validateForm()">验证表单</button>
      <button type="button" onclick="resetCustomValidation()">重置自定义验证</button>
    </form>
    <form oninput="result.value=parseInt(a.value)+parseInt(b.value)">
      <input type="range" id="a" value="50">+
      <input type="number" id="b" value="25">
      =
      <output name="result" for="a b">75</output>
    </form>
  </main>
  <script>
    // 获取表单元素
    const form = document.querySelector('form');
    const customInput = document.getElementById('custom');
    const customError = document.getElementById('custom-error');

    // 表单验证函数
    function validateForm() {
      // 检查整个表单的有效性
      if (form.checkValidity()) {
        alert('表单验证通过!');
      } else {
        // 检查单个输入的有效性
        const emailInput = document.getElementById('email');
        if (!emailInput.checkValidity()) {
          emailInput.reportValidity(); // 这会显示原生的验证提示
          return;
        }

        // 检查数字输入的有效性
        const numberInput = document.getElementById('number');
        if (!numberInput.checkValidity()) {
          numberInput.reportValidity();
          return;
        }
        
        alert('表单验证失败!');
      }
    }

    // 自定义验证示例
    customInput.addEventListener('input', function () {
      if (this.value.length < 5) {
        this.setCustomValidity('输入必须至少5个字符');
        customError.textContent = '输入必须至少5个字符';
      } else {
        this.setCustomValidity('');
        customError.textContent = '';
      }
    });

    // 重置自定义验证
    function resetCustomValidation() {
      customInput.setCustomValidity('');
      customError.textContent = '';
      customInput.value = '';
    }

    // 显示验证状态信息
    customInput.addEventListener('invalid', function (e) {
      e.preventDefault();
      customError.textContent = customInput.validationMessage;
    });

    // 显示验证状态信息
    customInput.addEventListener('input', function () {
      if (customInput.validity.valid) {
        customError.textContent = '';
      }
    });
  </script>
</body>

</html>

Contributors

Annan

写代码是热爱,写到世界充满爱