要实现表格悬停高亮需分场景:整行高亮须显式写并用tbody tr:hover;td:hover仅作用于单元格;精准字符高亮必须用JS的Range API;移动端无hover,需用@media(hover: hover)或touch事件兜底。

直接给 <textarea></textarea> 或 <input type="text"> 套在表格里,再用 :hover 是没用的——它们本身不支持子元素级文本高亮,tr:hover 也管不到内部文字。真要实现“悬停时高亮表格中某段文字”,得区分场景:是整行高亮、整列高亮,还是精准到单元格内某几个字符?下面分情况说清楚。
tbody tr:hover 只对整行有效,但必须显式写 tbody
很多人写 tr:hover { background-color: #eee; } 没反应,不是 CSS 错了,而是 HTML 结构缺了 <tbody>。浏览器会自动补全 DOM 中的 <code>tbody,但 CSS 选择器 tbody tr:hover 不匹配“隐式生成”的那一层。
- ✅ 正确结构:
<table> <thead>...</thead> <tbody><tr><td>data</td></tr></tbody> </table> - ❌ 错误结构:
<table><tr><td>data</td></tr></table>(tr直接挂table下) - Vue/React 中别用
<fragment></fragment>或空标签包裹tr,否则tbody就没了 - Bootstrap 用户注意:
.table-hover的规则是.table-hover > tbody > tr:hover,漏掉任一>都失效
td:hover 和 tr:hover 的行为差异很关键
td:hover 是“点哪亮哪”,tr:hover 是“扫过即亮”。选错会影响用户直觉,尤其当表格有 colspan 或 rowspan 时。
-
td:hover无法触发整行样式(比如字体加粗),除非额外加 JS -
td:hover在跨单元格区域会漏掉部分,tr:hover更稳定 - 如果同时写了两个,
td:hover优先级更高,可能覆盖tr:hover的背景色——注意声明顺序 - 想让
td:hover看起来像整行,可以写td:hover, td:hover + td { background-color: #f8f9fa; },但兼容性差,不推荐
单元格内精确高亮某段文本要用 JS + Range API
纯 CSS 搞不定单元格里“只高亮‘错误’这两个字”。<td> 不是表单控件,<code>setSelectionRange() 不可用,必须靠 Range 和 Selection。
立即学习“前端免费学习笔记(深入)”;
- 前提:目标文本得在单一文本节点内;如果有
<strong></strong>或其他标签,得递归遍历找对应Text节点 - 不能直接改
innerHTML插<mark></mark>,会破坏事件绑定和已有样式 - 示例核心逻辑:
const range = document.createRange(); range.selectNodeContents(textNode); range.setStart(textNode, startIndex); range.setEnd(textNode, endIndex); window.getSelection().removeAllRanges(); window.getSelection().addRange(range); - 高亮后记得调用
window.getSelection().removeAllRanges()清除选区,否则影响后续交互
移动端根本没 hover,别硬套 CSS
iOS Safari 和 Android Chrome 在非链接元素上基本不触发 :hover,这是规范行为,不是 bug。首次触摸后短暂激活,之后就卡住或失效。
- 别用
tr:hover做关键操作反馈(比如“点这里删除”) - 兜底方案一:
@media (hover: hover) { tbody tr:hover { ... } },仅在支持设备启用 - 兜底方案二:监听
touchstart给tr加is-touched类,touchend后延迟 150ms 移除,防点击残留 - 千万别用
mouseover/mouseout替代——手机上几乎不触发
真正麻烦的从来不是那行 tr:hover,而是你忘了 td { background-color: inherit; },或者被一个没注意到的 pointer-events: none 拦住了,又或者在 iPad 上点了第一行后,它就永远“亮着”——这些细节漏掉一个,效果就等于没做。



















