如何实现HTML表格中rowspan单元格的匹配对应部分高亮?
问题描述
我有如下结构的HTML表格:
表格初始样式:第一列是分组列(group),group1占3行,对应三个名称项:amy、test、amy2;group2占1行,对应名称项water。
<table> <thead> <tr> <th>no.</th> <th>name</th> </tr> </thead> <tbody id="list"> <tr> <td class="group" id="group_1" rowspan="3">1</td> <td id="name_1">amy</td> </tr> <tr> <td id="name_1">test</td> </tr> <tr> <td id="name_1">amy2</td> </tr> <tr> <td class="group" id="group_2">2</td> <td id="name_2">water</td> </tr> </tbody> </table>
我写了一段JavaScript实现搜索高亮功能:
function highlightKeyword() { let searchWord = document.getElementById("search").value.toLowerCase().replace(/\s+/g, ''); let rows = document.getElementById("list").getElementsByTagName("tr"); for (let i = 0; i < rows.length; i++) { let targetName = rows[i].getElementsByTagName("td")[rows[i].getElementsByTagName("td").length - 1]; let name = targetName.textContent.toLowerCase().replace(/\s+/g, ''); let targetCode = targetName['id'].substr(5); let groupTd = document.getElementById(`group_${targetCode}`); if (searchWord != "") { if (name.includes(searchWord)) { rows[i].classList.add("highlighted-row"); groupTd.classList.add("highlighted-row"); } else { rows[i].classList.remove("highlighted-row"); groupTd.classList.remove("highlighted-row"); } } else { rows[i].classList.remove("highlighted-row"); groupTd.classList.remove("highlighted-row"); } } }
现在的功能是搜索框匹配name列内容时,会高亮对应的行以及整个rowspan的分组单元格。但我想要的效果是:仅高亮rowspan分组单元格中与匹配行对应的区域,比如搜索“amy”时,amy和amy2所在的行高亮,同时分组列中这两行对应的区域也变黄,而test行对应的分组区域保持原样,不是整个分组单元格都变黄。
请问实现这个效果的最简方法是什么?
以下是完整可运行代码片段:
function highlightKeyword() { let searchWord = document.getElementById("search").value.toLowerCase().replace(/\s+/g, ''); let rows = document.getElementById("list").getElementsByTagName("tr"); for (let i = 0; i < rows.length; i++) { let targetName = rows[i].getElementsByTagName("td")[rows[i].getElementsByTagName("td").length - 1]; let name = targetName.textContent.toLowerCase().replace(/\s+/g, ''); let targetCode = targetName['id'].substr(5); let groupTd = document.getElementById(`group_${targetCode}`); if (searchWord != "") { if (name.includes(searchWord)) { rows[i].classList.add("highlighted-row"); groupTd.classList.add("highlighted-row"); } else { rows[i].classList.remove("highlighted-row"); groupTd.classList.remove("highlighted-row"); } } else { rows[i].classList.remove("highlighted-row"); groupTd.classList.remove("highlighted-row"); } } }
.highlighted-row { background-color: yellow; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <input class="form-control w-30" id="search" oninput="highlightKeyword()"> <table class="table table-sm table-bordered"> <thead> <tr> <th>group.</th> <th>name</th> </tr> </thead> <tbody id="list"> <tr> <td class="group" id="group_1" rowspan="3">1</td> <td id="name_1">amy</td> </tr> <tr> <td id="name_1">test</td> </tr> <tr> <td id="name_1">amy2</td> </tr> <tr> <td class="group" id="group_2">2</td> <td id="name_2">water</td> </tr> </tbody> </table>
最简实现方法
核心思路是通过给无分组单元格的行添加占位td,让占位td和rowspan的分组单元格重叠,再通过行高亮控制占位td的背景,模拟出分组单元格局部高亮的效果,具体步骤如下:
1. 补全HTML表格结构
给每个没有分组单元格的<tr>添加一个空的<td class="group-placeholder"></td>,保证表格列数对齐:
<tbody id="list"> <tr> <td class="group" id="group_1" rowspan="3">1</td> <td id="name_1">amy</td> </tr> <tr> <td class="group-placeholder"></td> <td id="name_1">test</td> </tr> <tr> <td class="group-placeholder"></td> <td id="name_1">amy2</td> </tr> <tr> <td class="group" id="group_2">2</td> <td id="name_2">water</td> </tr> </tbody>
2. 调整CSS样式
让占位td和分组单元格重叠,默认隐藏边框,高亮时显示背景:
/* 单元格设为相对定位,方便层级控制 */ .table td { position: relative; } /* 去掉占位td的边框和内边距,和分组单元格完全重叠 */ .group-placeholder { border: none !important; padding: 0; } /* 高亮行时,给该行所有td加背景色 */ .highlighted-row td { background-color: yellow; } /* 分组单元格在底层,占位td在上层,确保高亮背景能显示出来 */ .group { z-index: 0; } .group-placeholder { z-index: 1; }
3. 简化JavaScript逻辑
不再操作分组单元格的类,只需要根据搜索结果控制行的高亮状态:
function highlightKeyword() { let searchWord = document.getElementById("search").value.toLowerCase().replace(/\s+/g, ''); let rows = document.getElementById("list").getElementsByTagName("tr"); for (let row of rows) { let targetName = row.querySelector("td[id^='name_']"); let name = targetName.textContent.toLowerCase().replace(/\s+/g, ''); // 根据是否匹配切换高亮类 row.classList.toggle("highlighted-row", searchWord && name.includes(searchWord)); } }
效果说明
当搜索匹配某一行时,该行的占位td会显示黄色背景,刚好覆盖分组单元格的对应区域,视觉上就像分组单元格的局部被高亮了;未匹配的行,占位td保持透明,不影响原有分组单元格的显示。
内容的提问来源于stack exchange,提问作者mentha
相关产品推荐
相关产品推荐

