跳到主要内容

HTML 表单与表格

表单和表格是网页中用于与用户交互和展示数据的重要元素。表单让用户能够输入、提交数据,表格则让数据以结构化的方式清晰呈现。这一章将详细介绍它们的用法。

表单基础

表单是网页与用户交互的核心机制。用户通过表单输入信息,表单将数据提交给服务器处理。常见的表单应用包括登录注册、搜索框、问卷调查、评论留言等。

一个完整的表单由 <form> 元素包裹,内部包含各种输入控件:

<form action="/submit" method="POST">
<label for="username">用户名:</label>
<input type="text" id="username" name="username">

<label for="password">密码:</label>
<input type="password" id="password" name="password">

<button type="submit">登录</button>
</form>

form 元素的属性

<form> 元素本身有几个重要属性:

<form 
action="/api/login"
method="POST"
enctype="multipart/form-data"
target="_blank"
autocomplete="on"
novalidate
>
<!-- 表单控件 -->
</form>

action 指定表单提交的目标 URL。如果省略,表单会提交到当前页面的 URL。

method 指定提交方式,最常用的是 GETPOST。GET 将数据附加在 URL 后面,适合简单的查询;POST 将数据放在请求体中,适合敏感信息或大量数据。

enctype 指定表单数据的编码方式。默认是 application/x-www-form-urlencoded,如果表单包含文件上传,必须设置为 multipart/form-data

autocomplete 控制浏览器自动填充功能。设为 on 启用,设为 off 禁用。

novalidate 如果存在,表单提交时不进行原生验证。

输入控件

input 元素

<input> 是最常用的表单控件,通过 type 属性可以创建多种输入类型:

<!-- 文本输入 -->
<input type="text" name="username" placeholder="请输入用户名">

<!-- 密码输入,字符会被遮盖 -->
<input type="password" name="password" placeholder="请输入密码">

<!-- 邮箱输入,会验证邮箱格式 -->
<input type="email" name="email" placeholder="请输入邮箱">

<!-- 数字输入,支持上下箭头调整 -->
<input type="number" name="age" min="1" max="150" step="1">

<!-- 电话号码输入,移动端会弹出数字键盘 -->
<input type="tel" name="phone" placeholder="请输入电话">

<!-- URL 输入,会验证 URL 格式 -->
<input type="url" name="website" placeholder="请输入网址">

<!-- 搜索框,某些浏览器会显示清除按钮 -->
<input type="search" name="keyword" placeholder="搜索...">

input 元素支持许多通用属性:

<input 
type="text"
name="username" <!-- 表单提交时的字段名 -->
id="username" <!-- 关联 label -->
value="默认值" <!-- 默认值 -->
placeholder="提示文字" <!-- 占位提示 -->
required <!-- 必填项 -->
disabled <!-- 禁用 -->
readonly <!-- 只读 -->
maxlength="20" <!-- 最大长度 -->
minlength="3" <!-- 最小长度 -->
pattern="[A-Za-z]{3,}" <!-- 正则验证 -->
autofocus <!-- 页面加载时自动聚焦 -->
autocomplete="off" <!-- 关闭自动填充 -->
>

日期时间输入

HTML5 提供了多种日期时间输入类型,浏览器会提供原生的日期选择器:

<!-- 日期选择 -->
<input type="date" name="birthday" min="1900-01-01" max="2024-12-31">

<!-- 时间选择 -->
<input type="time" name="meeting-time" min="09:00" max="18:00">

<!-- 日期时间选择 -->
<input type="datetime-local" name="appointment">

<!-- 月份选择 -->
<input type="month" name="expiry-month">

<!-- 周选择 -->
<input type="week" name="week-number">

这些输入类型的值格式是固定的:日期是 YYYY-MM-DD,时间是 HH:MM,datetime-local 是 YYYY-MM-DDTHH:MM

其他输入类型

<!-- 颜色选择器 -->
<input type="color" name="theme-color" value="#3498db">

<!-- 范围滑块 -->
<input type="range" name="volume" min="0" max="100" value="50">

<!-- 文件上传 -->
<input type="file" name="avatar" accept="image/*">

<!-- 多文件上传 -->
<input type="file" name="documents" multiple accept=".pdf,.doc,.docx">

<!-- 隐藏字段,用户不可见但会随表单提交 -->
<input type="hidden" name="user-id" value="12345">

文件上传时,accept 属性可以限制文件类型。image/* 接受所有图片,.pdf 接受 PDF 文件,multiple 属性允许选择多个文件。

单选框和复选框

单选框(radio)用于从多个选项中选择一个,复选框(checkbox)用于选择多个:

<!-- 单选框:同一组必须有相同的 name -->
<fieldset>
<legend>性别</legend>
<label>
<input type="radio" name="gender" value="male">
</label>
<label>
<input type="radio" name="gender" value="female">
</label>
<label>
<input type="radio" name="gender" value="other"> 其他
</label>
</fieldset>

<!-- 复选框 -->
<fieldset>
<legend>兴趣爱好</legend>
<label>
<input type="checkbox" name="hobby" value="reading"> 阅读
</label>
<label>
<input type="checkbox" name="hobby" value="gaming"> 游戏
</label>
<label>
<input type="checkbox" name="hobby" value="travel"> 旅行
</label>
</fieldset>

<!-- 默认选中 -->
<label>
<input type="checkbox" name="agree" value="yes" checked> 同意条款
</label>

单选框的关键是 name 属性——具有相同 name 的单选框互斥,只能选择其中一个。复选框则允许选择多个,每个被选中的值都会提交。

下拉选择框

<select> 元素创建下拉选择框:

<select name="country">
<option value="">请选择国家</option>
<option value="cn">中国</option>
<option value="us">美国</option>
<option value="uk">英国</option>
<option value="jp">日本</option>
</select>

<!-- 多选下拉框 -->
<select name="skills" multiple size="4">
<option value="html">HTML</option>
<option value="css">CSS</option>
<option value="js">JavaScript</option>
<option value="python">Python</option>
</select>

<!-- 分组选项 -->
<select name="car">
<optgroup label="德系">
<option value="benz">奔驰</option>
<option value="bmw">宝马</option>
<option value="audi">奥迪</option>
</optgroup>
<optgroup label="日系">
<option value="toyota">丰田</option>
<option value="honda">本田</option>
</optgroup>
</select>

multiple 属性允许多选,size 属性设置可见选项数量。<optgroup> 用于对选项进行分组,label 属性设置分组标题。

多行文本输入

<textarea> 用于输入多行文本:

<textarea 
name="message"
rows="4"
cols="50"
placeholder="请输入您的留言..."
maxlength="500"
>默认内容</textarea>

rows 设置可见行数,cols 设置可见列数。注意 textarea 是容器元素,默认值放在标签内部,而不是 value 属性。实际使用中,通常用 CSS 控制尺寸,而不是 rows 和 cols:

<textarea name="content" style="width: 100%; height: 200px;"></textarea>

标签与分组

label 元素

<label> 为表单控件提供说明文字,它有两种关联方式:

<!-- 方式一:使用 for 属性关联 input 的 id -->
<label for="email">邮箱:</label>
<input type="email" id="email" name="email">

<!-- 方式二:直接包裹 input -->
<label>
用户名:
<input type="text" name="username">
</label>

使用 label 很重要,因为它提升了用户体验和可访问性。点击 label 文字会自动聚焦到对应的输入框,这对移动端用户和屏幕阅读器用户都很有帮助。

fieldset 和 legend

<fieldset> 用于对相关表单控件进行分组,<legend> 提供分组标题:

<form>
<fieldset>
<legend>个人信息</legend>

<label for="name">姓名:</label>
<input type="text" id="name" name="name">

<label for="email">邮箱:</label>
<input type="email" id="email" name="email">
</fieldset>

<fieldset>
<legend>账户设置</legend>

<label for="username">用户名:</label>
<input type="text" id="username" name="username">

<label for="password">密码:</label>
<input type="password" id="password" name="password">
</fieldset>
</form>

fieldset 默认会显示边框,可以通过 CSS 调整样式。分组对长表单尤为重要,它让用户更容易理解表单结构。

按钮类型

表单中的按钮有三种类型:

<!-- 提交按钮:点击提交表单 -->
<button type="submit">提交</button>
<input type="submit" value="提交">

<!-- 重置按钮:点击重置表单到初始状态 -->
<button type="reset">重置</button>
<input type="reset" value="重置">

<!-- 普通按钮:不触发表单提交 -->
<button type="button">普通按钮</button>
<input type="button" value="普通按钮">

<button> 元素比 <input type="button"> 更灵活,因为它可以包含 HTML 内容,而 input 只能通过 value 属性设置纯文本:

<button type="submit">
<span class="icon"></span> 提交表单
</button>

表单验证

HTML5 提供了原生的表单验证功能,无需 JavaScript 即可实现基础验证:

<form>
<!-- required:必填 -->
<input type="text" name="name" required>

<!-- pattern:正则表达式验证 -->
<input type="text" name="phone" pattern="[0-9]{11}"
title="请输入11位手机号">

<!-- min/max:数值或日期范围 -->
<input type="number" name="age" min="1" max="150">

<!-- minlength/maxlength:文本长度 -->
<input type="password" name="password" minlength="6" maxlength="20">

<!-- 邮箱、URL 等类型自带格式验证 -->
<input type="email" name="email">

<button type="submit">提交</button>
</form>

当表单验证失败时,浏览器会显示默认的错误提示。可以通过 JavaScript 自定义验证逻辑和错误信息:

<form id="myForm">
<input type="password" id="password" name="password" required>
<input type="password" id="confirm" name="confirm" required>
<button type="submit">注册</button>
</form>

<script>
const form = document.getElementById('myForm');
const confirm = document.getElementById('confirm');

confirm.addEventListener('input', function() {
const password = document.getElementById('password').value;
if (this.value !== password) {
this.setCustomValidity('两次密码输入不一致');
} else {
this.setCustomValidity('');
}
});
</script>

setCustomValidity() 方法设置自定义验证消息。当消息不为空时,验证失败,表单无法提交。消息为空时,表示验证通过。

表格基础

表格用于展示结构化的数据。一个标准的表格包含表头、表体和可选的表尾:

<table>
<caption>学生成绩表</caption>
<thead>
<tr>
<th>姓名</th>
<th>语文</th>
<th>数学</th>
<th>英语</th>
</tr>
</thead>
<tbody>
<tr>
<td>张三</td>
<td>90</td>
<td>85</td>
<td>92</td>
</tr>
<tr>
<td>李四</td>
<td>88</td>
<td>95</td>
<td>87</td>
</tr>
</tbody>
<tfoot>
<tr>
<td>平均分</td>
<td>89</td>
<td>90</td>
<td>89.5</td>
</tr>
</tfoot>
</table>

表格结构元素

<table> 是表格的容器元素。内部的结构元素包括:

  • <caption>:表格标题,显示在表格上方
  • <thead>:表头区域,包含列标题
  • <tbody>:表体区域,包含数据行
  • <tfoot>:表尾区域,包含汇总或备注
  • <tr>:表格行
  • <th>:表头单元格,默认加粗居中
  • <td>:数据单元格

虽然可以省略 thead、tbody、tfoot 直接写 tr 和 td,但使用结构元素有以下好处:

  • 语义更清晰,便于理解表格结构
  • 打印长表格时,表头和表尾会在每页重复
  • 便于 CSS 选择器定位不同区域

单元格合并

colspan 属性让单元格跨多列,rowspan 属性让单元格跨多行:

<table>
<tr>
<th colspan="3">2024年销售数据</th>
</tr>
<tr>
<th>季度</th>
<th>产品A</th>
<th>产品B</th>
</tr>
<tr>
<td rowspan="2">上半年</td>
<td>100万</td>
<td>80万</td>
</tr>
<tr>
<td>110万</td>
<td>90万</td>
</tr>
<tr>
<td rowspan="2">下半年</td>
<td>120万</td>
<td>95万</td>
</tr>
<tr>
<td>130万</td>
<td>100万</td>
</tr>
</table>

使用单元格合并时要注意计算好行列数量,确保表格结构正确。一个常见的技巧是先画出完整的表格布局,再标注哪些单元格需要合并。

表格样式

HTML 表格默认没有边框和样式,需要通过 CSS 添加。以下是一个基本的表格样式:

<style>
table {
border-collapse: collapse; /* 合并边框 */
width: 100%;
}

th, td {
border: 1px solid #ddd;
padding: 12px;
text-align: left;
}

th {
background-color: #f5f5f5;
font-weight: bold;
}

/* 斑马纹效果 */
tr:nth-child(even) {
background-color: #fafafa;
}

/* 悬停高亮 */
tr:hover {
background-color: #f0f0f0;
}
</style>

border-collapse: collapse 是表格样式的关键属性。默认情况下,相邻单元格的边框是分离的(有间隙),设置 collapse 后边框合并为单线,更符合常见的表格样式。

响应式表格

当表格宽度超出屏幕时,可以添加横向滚动:

<div style="overflow-x: auto;">
<table>
<!-- 表格内容 -->
</table>
</div>

或者在移动端隐藏不重要的列:

@media (max-width: 600px) {
.optional-column {
display: none;
}
}

小结

这一章我们学习了:

  • 表单的基本结构,包括 form 元素和各种输入控件
  • input 的多种类型,从文本、密码到日期、文件上传
  • 单选框、复选框、下拉选择的使用方法
  • label、fieldset 等辅助元素的作用
  • HTML5 原生表单验证功能
  • 表格的结构和单元格合并
  • 表格的基本样式和响应式处理

表单是用户与网页交互的核心,理解各种控件的特点和适用场景非常重要。表格虽然结构简单,但合理使用能让数据呈现更加清晰。下一章我们将学习 HTML 语义化标签和多媒体元素。