table tr:first-child 失效是因为浏览器自动插入 tbody,使 tr 不是 table 的直接子元素;应显式使用 thead>tr 或 tbody>tr:first-child 等语义化选择器。

tr:first-child 看似合理,但实际在大多数表格结构中根本选不到第一行——因为 <tr> 通常不是 <code><table> 的直接第一个子元素。
<h3>为什么 <code>table tr:first-child 常常失效
浏览器解析 HTML 表格时,会自动补全缺失的语义容器。即使你写的是:
<table> <tr><th>姓名</th><th>年龄</th></tr> <tr><td>张三</td><td>25</td></tr> </table>
实际 DOM 中,<tr> 往往被包裹进 <code><tbody>(除非你显式写了 <code><thead> 或 <code><tbody>)。所以 <code><table> 的第一个子元素是 <code><tbody>,而不是 <code><tr>,<code>tr:first-child 自然不匹配。
- 检查开发者工具 Elements 面板,确认
<tr> 的父节点是不是 <code><tbody> 或 <code><thead> <li>若第一行是表头,应使用 <code>thead tr:first-child或更稳妥的thead > tr - 若第一行是数据行且没写
<tbody>,浏览器仍可能自动插入,不能依赖手写结构 <h3>可靠写法:用 <code>thead > tr或tbody > tr:first-child真正可控的方式是主动定义语义结构:
立即学习“前端免费学习笔记(深入)”;
- 把表头明确包在
<thead> 里 → 用 <code>thead > tr选中它(无需伪类,更稳定) - 把首行数据明确包在
<tbody> 里 → 用 <code>tbody > tr:first-child(注意>子选择器,避免误中嵌套<tr>) <li>如果必须兼容无 <code><thead>/</thead> <tbody> 的旧 HTML,可加一层 wrapper 类,比如 <code><table class="has-header">,再配 CSS:<code>.has-header tbody > tr:first-child, .has-header thead > tr:first-child和:first-of-type在表格里区别明显假设表格开头混有
<caption></caption>或注释节点:<table> <caption>用户列表</caption> <tr><th>ID</th></tr> <tr><td>1</td></tr> </table>
此时:
-
tr:first-child❌ 不生效(第一个子是<caption></caption>) -
tr:first-of-type✅ 匹配第一个<tr>,不管前面有什么 <li>但 <code>:first-of-type在某些老版 Safari 中支持较弱,生产环境慎用
真正要稳,就别靠浏览器自动补全结构;手动写
<thead> 或 <code><tbody>,然后用明确父子关系的选择器——伪类只是辅助,不是救命稻草。</tbody> -
- 把表头明确包在


















