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 指定提交方式,最常用的是 GET 和 POST。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 语义化标签和多媒体元素。