用 tr:nth-child(even) 实现斑马纹最稳妥,需注意 thead 是否干扰计数、hover 样式须后置、深色模式需媒体查询适配,避免 nth-of-type 和 background-image 等易错方案。

用 tr:nth-child(even) 选中偶数行并设置背景色
斑马纹本质就是让表格的奇偶行呈现不同背景色,最直接的方式是用 CSS 的 :nth-child() 伪类。注意必须作用在 tr 上,而不是 td 或 table —— 否则可能被子元素样式覆盖或失效。
常见错误是写成 tr:nth-child(2n)(虽然等价),但更推荐 tr:nth-child(even),语义清晰且兼容性更好(IE9+)。如果表格有 thead,需确认是否要跳过表头:默认 :nth-child 是按 DOM 顺序计数,thead > tr 会占掉前几个序号,导致 tbody 里第一行可能被误染色。
- 简单场景(无
thead或希望表头也参与计数):tr:nth-child(even) { background-color: #f5f5f5; } - 带
thead且只对tbody生效:tbody tr:nth-child(even) { background-color: #f5f5f5; } - 避免和 hover 冲突:后续定义
tr:hover时,务必写在:nth-child规则之后,否则 hover 效果可能被覆盖
为什么不用 tr:nth-of-type()?
:nth-of-type() 按标签类型计数,看似合理,但实际容易出错。比如表格里插了注释、空格文本节点不影响 :nth-child,但 :nth-of-type() 只认 tr 标签,看似更“精准”,可一旦 thead 和 tbody 并存,thead tr 和 tbody tr 是不同类型容器下的同名标签,:nth-of-type(even) 在 tbody 内部重新计数——这反而符合需求?不,问题在于:如果 tbody 前有 caption 或其他非 tr 元素,:nth-of-type 不受影响;但开发者往往误以为它和 :nth-child 行为一致,结果调试半天发现偶数行没上色。
- 结论:
:nth-child()行为可预测,文档明确,优先用它 - 例外情况:极少数需要忽略
thead且 DOM 结构混乱(比如服务端模板插入了不可控的 wrapperdiv),才考虑用 JS 动态加 class,而非依赖伪类
移动端适配和性能小坑
斑马纹在手机上缩放后可能因 subpixel 渲染导致某几行颜色轻微错位,肉眼可见“虚边”。这不是 bug,是浏览器对半像素背景的抗锯齿处理。解决方法很简单:给 table 加 border-collapse: collapse,并确保所有 td/th 没有 padding 导致高度不齐;再配合 tr { line-height: normal; } 防止字体渲染差异放大错觉。
- 别用
background-image模拟斑马纹(如线性渐变),既难维护又增加重绘开销 - 如果表格行数超 1000,
:nth-child性能毫无压力——它由浏览器引擎原生实现,不是 JS 循环 - 深色模式下记得同步定义
@media (prefers-color-scheme: dark)中的背景色,否则斑马纹可能变成黑底黑字
tr:nth-child(even) 是最稳的选择,但得盯住 thead 是否干扰计数,还有 hover 和深色模式这两处,稍不注意就白忙活。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











