Appearance
02|HTML 表单、表格与语义化
页面不只是展示内容,还需要收集用户输入和呈现结构化数据。表单负责收集输入,表格负责展示行列数据,语义化标签则让页面结构对浏览器、搜索引擎和辅助技术更友好。
一、表单基础
表单用 <form> 包裹一组输入控件,用户填写后提交给服务器处理:
html
<form action="/api/login" method="post">
<label for="username">用户名</label>
<input type="text" id="username" name="username" placeholder="请输入用户名">
<label for="password">密码</label>
<input type="password" id="password" name="password">
<button type="submit">登录</button>
</form>| 属性 | 作用 |
|---|---|
action | 数据提交到的 URL |
method | HTTP 方法,常用 get 或 post |
name | 字段名,提交时作为键名 |
id | 唯一标识,与 label 的 for 关联 |
placeholder | 输入框为空时显示的提示文字 |
label 的 for 必须等于对应 input 的 id。这样点击标签文字时,焦点会自动跳到输入框,对触摸屏和屏幕阅读器都更友好。
常见 input 类型
html
<!-- 文本 -->
<input type="text" name="title">
<!-- 密码(输入内容显示为圆点) -->
<input type="password" name="pwd">
<!-- 邮箱(移动端会弹出邮箱键盘) -->
<input type="email" name="email">
<!-- 数字(带增减按钮) -->
<input type="number" name="count" min="0" max="100">
<!-- 日期选择器 -->
<input type="date" name="birthday">
<!-- 单选 -->
<input type="radio" name="role" value="admin" id="r1">
<label for="r1">管理员</label>
<input type="radio" name="role" value="user" id="r2">
<label for="r2">普通用户</label>
<!-- 多选 -->
<input type="checkbox" name="tags" value="python" id="t1">
<label for="t1">Python</label>
<input type="checkbox" name="tags" value="go" id="t2">
<label for="t2">Go</label>同一组单选按钮的 name 必须相同,这样浏览器才会把它们当成互斥选项。多选框的 name 也可以相同,提交时该字段会包含多个值。
下拉选择
html
<label for="env">环境</label>
<select id="env" name="env">
<option value="dev">开发环境</option>
<option value="test">测试环境</option>
<option value="prod" selected>生产环境</option>
</select>selected 表示默认选中项。如果没有 selected,默认选中第一项。
多行文本
html
<label for="desc">描述</label>
<textarea id="desc" name="desc" rows="4" cols="50"></textarea>textarea 适合长文本输入。rows 和 cols 定义初始尺寸,实际大小通常用 CSS 控制。
表单提交行为
html
<form action="/api/articles" method="post">
<input type="text" name="title" required>
<input type="text" name="author">
<button type="submit">提交</button>
</form>点击提交按钮后,浏览器会构造 HTTP 请求:
| method | 数据位置 | URL 示例 |
|---|---|---|
get | URL 查询参数 | /api/articles?title=xxx&author=yyy |
post | 请求体 | URL 是 /api/articles,数据在 body 中 |
required 属性会在提交前进行基础校验:如果该字段为空,浏览器会阻止提交并提示用户。但这只是前端校验,后端必须再次校验所有输入。
在现代单页应用(Vue/React)中,表单通常不通过原生 form 提交,而是用 JavaScript 拦截提交事件、收集数据、通过 fetch 发送。此时 action 和 method 可以省略,name 用于标识字段,button type="submit" 触发提交事件。
二、表格
表格用行(tr)和单元格(td / th)组织数据:
html
<table>
<thead>
<tr>
<th>主机名</th>
<th>IP 地址</th>
<th>状态</th>
</tr>
</thead>
<tbody>
<tr>
<td>web-01</td>
<td>192.168.1.10</td>
<td>运行中</td>
</tr>
<tr>
<td>web-02</td>
<td>192.168.1.11</td>
<td>已停止</td>
</tr>
</tbody>
</table>| 标签 | 作用 |
|---|---|
table | 表格容器 |
thead | 表头区域 |
tbody | 数据主体区域 |
tr | 一行 |
th | 表头单元格(默认加粗居中) |
td | 普通数据单元格 |
thead 和 tbody 不是强制标签,但显式分组有助于 CSS 选择器定位,也让屏幕阅读器能正确朗读表头与数据的对应关系。
跨行与跨列
html
<table>
<tr>
<th rowspan="2">服务</th>
<th colspan="2">资源占用</th>
</tr>
<tr>
<th>CPU</th>
<th>内存</th>
</tr>
<tr>
<td>Nginx</td>
<td>2%</td>
<td>128MB</td>
</tr>
</table>| 属性 | 作用 |
|---|---|
colspan="n" | 单元格横向占据 n 列 |
rowspan="n" | 单元格纵向占据 n 行 |
使用跨行跨列时,对应位置的 td 或 th 需要省略,否则表格结构会错乱。
三、语义化标签
HTML5 引入了一组具有明确语义的结构性标签,替代滥用 div 的做法:
html
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<title>运维管理平台</title>
</head>
<body>
<header>
<h1>运维管理平台</h1>
<nav>
<a href="/">首页</a>
<a href="/assets">资产</a>
<a href="/tasks">任务</a>
</nav>
</header>
<main>
<article>
<h2>今日告警</h2>
<p>共 3 条未处理告警...</p>
</article>
<aside>
<h3>快捷操作</h3>
<ul>
<li><a href="/tasks/new">新建任务</a></li>
</ul>
</aside>
</main>
<footer>
<p>© 2026 运维团队</p>
</footer>
</body>
</html>| 标签 | 语义 | 类比 |
|---|---|---|
header | 页面或区块的头部 | 原来的 div class="header" |
nav | 导航链接区域 | 原来的 div class="nav" |
main | 页面主要内容(每页应只有一个) | 原来的 div class="main" |
article | 独立的内容块,可以单独分发 | 文章、帖子、评论 |
section | 主题性内容分组 | 章节、区块 |
aside | 与主要内容相关的侧边信息 | 侧边栏、提示框 |
footer | 页面或区块的底部 | 原来的 div class="footer" |
语义化标签本身不改变外观——所有标签在浏览器默认样式下都是块级元素,前后换行。它们的价值在于:
- 搜索引擎更容易理解页面结构,有助于 SEO
- 屏幕阅读器可以为用户提供页面导航(如"跳到主要内容")
- 代码可读性提高,维护时一眼看出各区域用途
四、meta 元信息
head 中的 meta 标签携带浏览器和搜索引擎需要的元信息:
html
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="运维管理平台 - 资产管理、任务调度、事件记录">
<title>运维管理平台</title>
<link rel="stylesheet" href="/style.css">
</head>| meta 标签 | 作用 |
|---|---|
charset="utf-8" | 字符编码,防止中文乱码 |
viewport | 控制移动端缩放行为,响应式页面必须 |
description | 搜索引擎结果页显示的摘要 |
viewport 的含义:
html
<meta name="viewport" content="width=device-width, initial-scale=1.0">| 值 | 含义 |
|---|---|
width=device-width | 视口宽度等于设备屏幕宽度 |
initial-scale=1.0 | 初始缩放比例为 1,不放大也不缩小 |
缺少 viewport 时,移动端浏览器会按桌面宽度渲染页面,导致文字过小、需要手动缩放。
五、常见错误
用 div 代替语义化标签
html
<!-- 不建议 -->
<div class="header">...</div>
<div class="nav">...</div>
<div class="main">...</div>
<!-- 建议 -->
<header>...</header>
<nav>...</nav>
<main>...</main>语义化标签不会增加代码复杂度,反而提高了可维护性。只有在确实找不到合适语义标签时,才回退到 div。
表单缺少 label
html
<!-- 错误:没有 label,点击文字无法聚焦输入框 -->
用户名 <input type="text" name="username">
<!-- 正确 -->
<label for="username">用户名</label>
<input type="text" id="username" name="username">table 用于布局
html
<!-- 错误:用 table 做页面整体布局 -->
<table>
<tr><td>左侧栏</td><td>主内容</td></tr>
</table>表格只应用于展示表格数据。页面布局应使用 CSS(Flexbox、Grid)或语义化标签配合 CSS 实现。