双行表头必须用两个,不能塞进同一行;正确做法是首行用rowspan和colspan定义分组,次行写具体子项,所有须置于内。

双行表头必须用两个 <tr>,不能塞进同一行
<p>双行表头不是靠在同一个 <code><tr> 里写多个 <code><th> 实现的。常见错误是这样写:<code><tr>
<th>班级</th>
<th>学科</th>
<th>语文</th>
<th>数学</th>
</tr>——结果语义错乱、屏幕阅读器读成四列,且“学科”无法真正统管“语文”“数学”。
正确做法是拆成两行 <tr>,靠 <code>rowspan 和 colspan 建立层级关系:
<th rowspan="2"> 用于纵向贯穿多行的列(如“班级”) <li><code><th colspan="2"> 用于横向合并多列的表头(如“学科”) <li>第二行 <code><tr> 只放被 <code>colspan覆盖下的具体子项(如“语文”“数学”)- 所有
<th> 必须严格放在 <code><thead> 内,<code><tbody> 中禁止出现 <code><th> <p>示例:</p> <pre class="brush:php;toolbar:false;"><thead> <tr> <th rowspan="2">班级</th> <th colspan="2">学科</th> </tr> <tr> <th>语文</th> <th>数学</th> </tr> </thead></pre> <h3> <code>rowspan和colspan的数值必须“算得清”浏览器不会帮你校验跨行/跨列是否填满整行。如果
colspan="2"后只跟一个<th>,总列数就对不上,渲染时会自动补空单元格或错位——尤其在动态生成表格时容易出隐形 bug。<p><span>立即学习</span>“<a href="https://pan.quark.cn/s/cb6835dc7db1" style="text-decoration: underline !important; color: blue; font-weight: bolder;" rel="nofollow" target="_blank">前端免费学习笔记(深入)</a>”;</p> <p>检查要点:</p><div class="aritcle_card flexRow"> <div class="artcardd flexRow"> <a class="aritcle_card_img" href="/xiazai/skill12116" title="DeepBI DHTML 页面生成器"><img src="https://img.php.cn/upload/skill/001/246/273/6adaf20d3191a227.jpg" alt="DeepBI DHTML 页面生成器" ></a> <div class="aritcle_card_info flexColumn"> <a href="/xiazai/skill12116" title="DeepBI DHTML 页面生成器">DeepBI DHTML 页面生成器</a> <p>生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur</p> </div> <a href="/xiazai/skill12116" title="DeepBI DHTML 页面生成器" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div> <ul><li>每一行 <code><tr> 内所有 <code>colspan值之和,必须等于该表格定义的总列数(比如你有 3 列,那某行<th colspan="2"></th> <th></th>是合法的,但<th colspan="2"></th>单独一行就不行) -
rowspan不影响当前行计数,但会影响后续行的可用单元格数量;若某列被上一行rowspan="3"占用,接下来两行就不能再往该列位置放新单元格 - 别写
rowspan="1"或colspan="1"——这是默认值,显式声明反而干扰可维护性 - 需要“行标题”?用
<td scope="row">,它既保持语义又完全合法 <li>需要“列标题”在每行重复显示?那是视觉需求,应靠 CSS <code>position: sticky或 JS 滚动同步实现,而不是在<tbody> 里硬塞 <code><th> <h3><code><tfoot> 必须写在 <code><tbody> 之前 <p>虽然多数现代浏览器能容忍 <code><tfoot> 放在 <code><tbody> 后面,但这是不合规的。HTML 渲染机制要求浏览器提前知道页脚内容,以便支持分页打印、固定页脚、<code>display: table-footer-group等特性。旧版 Safari 或某些 PDF 导出工具会直接失效。标准顺序唯一合法写法是:
<table> <thead>...</thead> <tfoot>...</tfoot> <tbody>...</tbody> </table>
视觉上想让页脚显示在底部?不要靠 DOM 顺序,用 CSS 控制:
tfoot { display: table-row-group; }是默认行为;如需粘底,配合容器高度 +position: sticky。
为什么 <tbody> 里不能放 <code><th>
<p>HTML 规范明确规定:<code><tbody> 的直接子元素只能是 <code><tr>,而 <code><tr> 在 <code><tbody> 中只允许包含 <code><td>。一旦写了 <code><th>,浏览器可能静默纠错(比如把 <code><th> 提到 <code><thead> 外),但语义已损坏:ARIA 屏幕阅读器会跳过或误判,W3C Validator 会直接报错 <code>Element th not allowed as child of element tbody。
替代方案:


















