两个属性实现表头固定(table 的 thead 位置固定) | 如何实现表头固定 | 怎样能让表头固定 | display:sticky 方式固定表格表头
【先看图】
【基础版:说明问题】
<table> <thead style="position:sticky;top:0;"> <tr> <th>序号列头</th> <th>数据列头</th> </tr> </thead> <tbody> @for (int i = 0; i < 200; i++) { <tr> <td>序号列</td> <td>数据列</td> </tr> } </tbody> </table>
只要给thead加上"position:sticky;top:0;"的样式就可以实现表头固定了,列宽仍能保持自动调整的能力。这个方法简单易行,适应各种布局,完全没有兼容性的问题。
网上漂浮着两种方案:
第一种是给thead设置 display: table,table-layout: fixed; ,然后给 tbody 下的 tr 也设置 display: table; table-layout: fixed; ,这个方案有两个问题,第一是td的列宽失去了自适应宽度的能力,必须在内容比较宽的列加上宽度限制,否则会出现内容堆叠,第二是滚动条的位置不好处理,还得加一个滚动条一样宽的th和一个宽为0的td来修正列头右侧,否则会看上去有一个滚动条宽度的错位。
第二种是使用trasform让它始终吸在顶部,这种更不可取,父容器的布局稍微一复杂,就会出现无法预期的错位,而且td宽度基本会失控。
网上这些作者就是在自己的样式上下文和数据格式基础上试出一种方案就放在网上,并不是通用的。
我这个百搭,适应各种场景。
【优化版:解决细节问题】
<table style="border-collapse: collapse;text-align:center;width:100%;white-space:nowrap;"> <thead style="position:sticky;top:0;background-color:white;"> <tr> <th style="border-left: 1px solid #ccc; border-right: 1px solid #ccc; border-top: none; border-bottom: none;">序号列头</th> <th style="border-left: 1px solid #ccc; border-right: 1px solid #ccc; border-top: none; border-bottom: none;">数据列头</th> </tr> </thead> <tbody> @for (int i = 0; i < 200; i++) { @if (i == 0) { <tr> <td style="border: 1px solid #ccc; border-top: none;">@(i+1)</td> <td style="border: 1px solid #ccc; border-top: none;">数据@(i+1)</td> </tr> } else { <tr> <td style="border: 1px solid #ccc;">@(i+1)</td> <td style="border: 1px solid #ccc;">数据@(i+1)</td> </tr> } } </tbody> </table>
1、white-space:nowrap; 解决折行问题,不折行更美观,需要折行就去掉;
2、thead里的th,我多次测试,把上下边框去掉,保留与td相同样式的左右边框,同时设置一个喜欢的背景色(同时这个背景色还可以顺带解决下方td向上滚动时的th背景透明产生的重叠问题),可达到最佳视觉效果,去掉上下边框的原因是,sticky+top:0生效的时候,上下边框会出现镂空,不好解决,去掉最无伤,如果非要精确和td一样高,就加上下padding实现;
3、tbody里第一行的td,要把上边框去掉,否则在滚动表格行的时候,表头下部会有边框的一个跳动,用此方法可以解除,视觉上看起来比较稳;
4、table存在于一个父元素之内的时候:比如父容器是一个有高度设置的div,因此需要限制table高度,且table滚动条自适应,这个也非常简单,只要把这个外层div设置overflow-auto就可以、position最好是relative,以适配thead的top:0,而且这个div可以是flex block 各种display状态以及百分比 flex-strenth vh各种高度设置,都完美适配。
此方法简单易行,无副作用,适用于所有需要表头固定的场景。