最直接写法是tbody tr:nth-child(odd)和tbody tr:nth-child(even),因:nth-child按父元素所有子元素位置计数,需限定tbody避免thead干扰;ie8不支持,动态场景建议用class手动标记。

tr:nth-child(odd) 和 tr:nth-child(even) 是最直接的写法
不用 JavaScript,纯 CSS 就能搞定隔行换色,关键在于正确理解 :nth-child() 的行为。它选的是父元素下的第 N 个子元素,而表格里 tr 通常直接在 tbody 或 table 下,所以直接对 tr 使用即可。
常见错误是写成 tr:nth-of-type(odd) —— 这在有 thead、tfoot 或合并单元格时容易错位;或者把样式加在 td 上却忘了 th,导致表头颜色不一致。
- 推荐写法:
tbody tr:nth-child(odd) { background-color: #f5f5f5; } tbody tr:nth-child(even) { background-color: #ffffff; } - 如果表格没写
tbody,浏览器会自动补上,但显式写出更可控,避免意外被thead干扰 - 注意:IE8 不支持
:nth-child(),如需兼容,得用 JS 或 class 手动标记
用 class 控制更灵活,适合动态增删行场景
当表格内容由 JS 动态插入(比如通过 insertRow() 或框架渲染),CSS 伪类可能因 DOM 结构变化失效或延迟生效。此时给每行手动加 class 更稳。
例如后端返回数据后,循环生成 tr 时根据索引判断:
row.className = i % 2 === 0 ? 'row-even' : 'row-odd';
- 对应 CSS:
.row-odd { background-color: #f9f9f9; } .row-even { background-color: #ffffff; } - 好处是样式完全可控,方便配合状态类(如
.row-selected)叠加使用 - 缺点是多了一次 DOM 操作或模板拼接逻辑,小项目没必要过度设计
border-collapse: collapse 下要注意背景色被边框遮盖
启用 border-collapse: collapse 后,tr 的背景色可能被相邻 td 的边框“切掉”一像素,尤其在深色背景下明显。
- 解决方法:给
td和th也设相同背景色,或改用border-spacing: 0+border-collapse: separate - 更稳妥的做法是把背景色设在
td, th上而非tr:tbody tr:nth-child(odd) td, tbody tr:nth-child(odd) th { background-color: #f5f5f5; } - 注意
th默认有加粗和居中,别漏掉它,否则表头颜色会突兀
可访问性与打印样式常被忽略
隔行换色对屏幕阅读器无影响,但打印时默认会丢弃背景色,导致纸质文档失去区分度。
- 加一句
@media print覆盖:@media print { tbody tr:nth-child(odd) td, tbody tr:nth-child(odd) th { background-color: #e0e0e0 !important; } } - 深色主题下,若用户系统启用了
prefers-color-scheme: dark,建议同步适配:@media (prefers-color-scheme: dark) { tbody tr:nth-child(odd) { background-color: #333; } tbody tr:nth-child(even) { background-color: #444; } } - 别忘了检查对比度:浅灰背景配黑字要满足 WCAG AA 级(至少 4.5:1),可用工具验证
tr:nth-child(odd) 够用,但一旦涉及动态内容、打印需求或深色模式,就得提前考虑这些边界。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











