鼠标悬停<tr>时动态调整表格高度,解决CSS hover闪烁问题
首先得说清楚你遇到的闪烁问题根源:当你用tr:hover + #test这种相邻兄弟选择器时,一旦鼠标移到刚显示出来的隐藏行上,原来的触发行(那个tr)就失去了hover状态,隐藏行立刻被隐藏;接着鼠标又回到触发行,再次触发显示——这来回切换就导致了闪烁。而且你用display: none和display: table-row切换的话,没法用过渡动画,状态变化是瞬间的,也会加重闪烁的视觉效果。
不用SCSS/LESS完全可以解决这个问题,我给你两个可行的纯CSS方案:
方案1:用tbody分组控制(最可靠)
把每个触发行和对应的隐藏行放在同一个<tbody>里,通过tbody的hover状态来控制隐藏行的显示——这样只要鼠标在这个tbody范围内(不管是触发行还是隐藏行),hover状态都会保持,彻底避免闪烁。
修改后的HTML
<table style="width:100%; table-layout: fixed" > <!-- 第一组:触发行+隐藏行 --> <tbody class="row-group"> <tr> <td>TEST</td> <td>TEST </td> <td>TEST</td> <td> TEST</td> </tr> <tr class="hidden-row"> <td>A</td> <td>B</td> <td>C</td> <td>D</td> </tr> </tbody> <!-- 第二组:触发行+隐藏行 --> <tbody class="row-group"> <tr> <td>E</td> <td>F </td> <td>G</td> <td>H </td> </tr> <tr class="hidden-row"> <td>I</td> <td>L</td> <td>M</td> <td>N</td> </tr> </tbody> <!-- 第三组:触发行+隐藏行 --> <tbody class="row-group"> <tr> <td>TEST</td> <td>TEST </td> <td>TEST</td> <td>TEST </td> </tr> <tr class="hidden-row"> <td>O</td> <td>P</td> <td>Q</td> <td>R</td> </tr> </tbody> </table>
修改后的CSS
table, tr, td { border: 1px solid black; border-collapse: collapse; /* 合并边框,让表格更美观 */ } .hidden-row { height: 0; overflow: hidden; transition: height 0.2s ease-in-out; /* 平滑过渡高度变化 */ } .row-group:hover .hidden-row { height: auto; /* 自动适应内容高度,也可以设固定值比如40px */ }
方案2:用通用兄弟选择器+触发行类(适合不想改HTML结构的情况)
如果不想调整HTML结构,你可以给所有触发行加一个统一的类(比如trigger-row),然后用通用兄弟选择器~来控制,但要注意,这个方法只适用于隐藏行紧跟在触发行后面的情况,而且要确保鼠标移到隐藏行时,触发行依然处于hover范围(比如给触发行加一点padding)。
CSS示例
table, tr, td { border: 1px solid black; border-collapse: collapse; } .hidden-row { height: 0; overflow: hidden; transition: height 0.2s ease-in-out; } .trigger-row:hover ~ .hidden-row { height: auto; }
注意点
这个方案的局限性是:如果触发行和隐藏行之间还有其他元素,通用兄弟选择器会选中所有后续的.hidden-row,所以不如tbody分组精准。
关于你问的「在tr:hover + #test中添加其他类」
当然可以,比如写成tr.trigger:hover + .hidden-row,但这本质还是相邻兄弟选择器,依然会有闪烁问题——因为鼠标移到隐藏行上时,触发行的hover状态就没了。所以核心不是加不加类,而是要让hover状态覆盖触发行和隐藏行的整个区域,这就是tbody分组方案更可靠的原因。
另外,把display切换换成height+overflow的方式,既能实现平滑过渡,也避免了display属性无法过渡导致的瞬间闪烁,一举两得。
内容的提问来源于stack exchange,提问作者Markus

