HTML+CSS+JS实现TABLE固定列(常见浏览器兼容)的最
佳实践
BS架构的企业级应⽤中,当⼀个表格列数较多时,⽤户⼀个常见的需求就是把前⾯⼏个重要的列固定住,这样拖动滚动条时固定的列会⽅便⽤户查看数据,⽤户体验很好。⼀些重量级的JS组件库也都有这个功能,那么有没有更简单的⽅法实现这个功能呢?
这个需求常见的解决⽅案是使⽤表格拼接的⽅法,这个⽅案如果要制作静态的⽹页,或者功能简单的动态页⾯,逻辑⽐较简单,技术上也不复杂,很容易实现,但是如果要做成组件,动态功能较多的话,就需要写⼤量的冗余代码,难以维护,甚⾄于⼀个简单的功能,都需要写很多的代码,⽐如事件处理等,这个⽅法就显得⽐较笨拙,灵活性很差,不是⼀个好的⽅案。
经过长时间的分析研究,各种场景的试验,我们到了⼀个兼容性⾮常好的解决⽅案,总体上来讲采⽤的是定位计算的⽅法,下⾯贴出代码,然后做个解读。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>⽆标题⽂档</title>
<script type="text/javascript">
function divScroll(scrollDiv){
var scrollLeft = scrollDiv.scrollLeft;
}
function divYScroll(scrollYDiv){
var scrollTop = scrollYDiv.scrollTop;
}
function onwheel(event){
var evt = event||window.event;
var bodyDivY = ElementById("tableDiv_y");
var scrollDivY = ElementById("scrollDiv_y");
if (bodyDivY.scrollHeight>bodyDivY.offsetHeight){
if (evt.deltaY){
bodyDivY.scrollTop = bodyDivY.scrollTop + evt.deltaY*7;
scrollDivY.scrollTop = scrollDivY.scrollTop + evt.deltaY*7;
}else{
bodyDivY.scrollTop = bodyDivY.scrollTop - evt.wheelDelta/5;
scrollDivY.scrollTop = scrollDivY.scrollTop - evt.wheelDelta/5;
}
}
}
</script>
<style type="text/css">
body {
margin:0;
padding:0;
}
table {
border-collapse:collapse;
border:0;
border:none;
}
table td  {
border:1px solid #000;
overflow:hidden;
padding:0 2px;
}
</style>
</style>
</head>
<body>
<div >
<div >
<div id="tableDiv_title" >
<table border="0" cellspacing="0" cellpadding="0"  >
<tr>
<td  >000</td>
<td  >⾃动表格</t        <td  style="min-width: 100px; m
ax-width: 100px;  width: 100px;" >56454⾃动</td>
<td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >最后⼀列</td>
</tr>
</table>
</div>
<div id="tableDiv_y" onmousewheel="onwheel(event);" onwheel="onwheel(event);">
<div id="tableDiv_body">
<table border="0" cellspacing="0" cellpadding="0" >
<tr>
<td  >001</td>
<td  >⾃动表格</td>            <td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >最后⼀列</td>
</tr>
<tr>
<td  >002</td>
<td  >⾃动表格</td>            <td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >最后⼀列</td>
</tr>
<tr>
<td  >003</td>
<td  >⾃动表格</td>
<td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >最后⼀列</td>
</tr>
<tr>
<td  >004</td>
<td  >⾃动表格</td>            <td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >最后⼀列</td>
</tr>
<tr>
<td  >005</td>
<td  >⾃动表格</td>            <td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >最后⼀列</td>
</tr>
<tr>
<td  >006</td>
<td  >⾃动表格</td>            <td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >最后⼀列</td>
</tr>
<tr>
<td  >007</td>
<td  >⾃动表格</td>            <td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >最后⼀列</td>
</tr>
<tr>
<td  >008</td>
<td  >⾃动表格</td>            <td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >最后⼀列</td>
</tr>
<tr>
<td  >009</td>
<td  >⾃动表格</td>            <td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >最后⼀列</td>
</tr>
<tr>
<td  >010</td>
<td  >⾃动表格</td>            <td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >56454⾃动</td>
<td  >最后⼀列</td>
</tr>
</table>
</div>
</div>
<div >
<div onscroll='divScroll(this);'>
<div ></div>
</div>
</div>
</div>
css设置表格滚动条</div>
<div id="scrollDiv_y" o            <div ></div>
</div>
</div>
</div>
</body>
</html>
⼀、总体结构:
页⾯基本元素为DIV+TABLE,固定的列采⽤绝对定位的⽅式固定,每⼀列都要指定固定宽度,为了解
决横竖滚动条的问题,表头
和表体的外⾯分别包裹两层DIV,滚动条采⽤虚拟的⽅式,固定在固定位置通过JS控制模拟正常DIV滚动条的效果。
⼆、定位:
固定的列要绝对定位,通过left属性控制左侧位移,为了保证固定列浮动在上⽅,设置z-index为1,。为了保证有竖滚动条时的正常
显⽰,表体的外层DIV为绝对定位,由此导致滚动条也都要绝对定位。还有,表头和表体以及滚动条的内层DIV通过margin-left属性控制左
侧外边距,把固定列的偏移量空余出来。
⼆、宽度计算:
每⼀列的宽度都要指定固定的值,并且要注意⼀个关键点,就是还要加上min-width和max-width属性,这两个属性和width值相
等,表头表体的内层DIV,宽度为auto,⾃适应表格宽度,外层DIV宽度为100%,最外层的DIV通过padding-right属性控制右侧内边距,
将竖滚动条的位置空余出来。
三、⾼度计算:
因为绝对定位的存在,整个表格组件的⾼度要指定,可以通过计算得出,竖滚动条的top值也需要进⾏计算。
四、滚动条:
本⽅案⼀个突出特点,就是虚拟的滚动条,就是通过⼀个和表格⼀样宽、⾼度为⼀个像素的DIV模拟出表体DIV的横向滚动条,竖滚
动条同理。之所以采⽤这个形式,⼀个是横向滚动条这样处理⽐较美观,竖滚动条这样处理之后,表头和表体的外层DIV宽度不⽤计算了,
都为100%,否则存在滚动条时,表头和横向滚动条要空出竖滚动条宽度的位移,否则⽆法对齐,这个计算倒不复杂,但是某些情况下存在
问题,在此不展开了。
五、滚动事件:
因为表体的滚动条都隐藏了,导致⿏标滚轮不起作⽤了,这样就需要⽤JS处理⿏标滚轮事件,本⽂的样例代码兼容常见浏览器。这
⾥的重点是同时写了onmousewheel和onwheel事件,onmousewheel兼容IE,在计算滚动距离时,注意deltaY和wheelDelta属性的差异
即可。
六、优缺点分析:
本⽂的解决⽅案已经经过精简,重点是讲清楚原理,在我们的实际中,⾮常的复杂。这个设计考虑了⾮常多的兼容性,包括了浏览
器的兼容性和各种场景的兼容性,如果需求简单,还有简化的空间。
这个⽅案的优点是,如果要做组件的话,因为HTML结构简单,表头和表体都是⼀个TABLE,JS控制代码⾮常⼲净,维护容易。缺
点就是计算过多。我们认为该⽅案⽐较适⽤于开发组件的情况,静态页⾯就有点⼩题⼤作了。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。