网页中单一表格横纵表头锁定的细节

五·一之前捣鼓了一个可以锁定横纵表头的HTML表格,不过那天急着回家就只给了一个 demo示例。这不长假过后又挺忙活,一拖就给拖到周末了。这个东西虽然不是什么新奇的玩意,不过里面的细节还是有不少,所以有知其然并希望知其所以然的博友,欢迎来一起讨论讨论。

    实现这个锁定表头的效果其实到有很多的方法,不过使用 单一表格来实现,需要借助IE的css支持的expression表达式关键字。另外就是对浏览器布局原理的理解,如果不熟悉可以参考我原来写的 两篇文章。所以要实现这个效果,我们需要也只需要做两件事情,一是使用css提供的expression功能;二是使用css提供的position修改布局方式的能力。

    首先我们来看上部表头的锁定,我们知道对于container元素,如果要限定内部内容的大小,并出现滚动条。因该是用如下css来定义可以作为容器的元素,这里我使用的是div来做为表格的容器,代码如下:
< div  onselectstart ="return false"  style ="border-color:Blue;border-width:2px;border-style:solid;height:100%;width:700px;overflow:auto;cursor:default;" >
<!--  table  -->
</ div >
// 重要的就是那个overflow:auto。顺便说一下,弄出滚动条这个css设置虽然非常的easy,不过不知道IE这么搞的,这个容器只能在height上设置百分比,而width的大小必须是 固定的值,否这width方向上就不能出现滚动条

    其实如果就这样我们把table放入div中,就已经是一个可以滚动的表格了,只是所有的单元格也都在滚动而已。所以我们需要修改表格中不希望滚动的单元格的布局方式,tr和td的默认布局方式都是static。如果要让tr相对于div不动,那么在div中的滚动条滚动到scrollTop为100时,相对不动的tr应该停留在相对于div左上角的(0, 100)的位置上。这个相对性我们可以用<tr style="position:relative">获得,那么top为100怎么弄呢?显然这就是expression的事情了,我们需要把行上的css设置为<tr style="top:expression(表格容器.scrollTop)">。这个表格容器是什么呢?就是div,使用dom的层次来查找因该是:
this .parentElement.parentElement.parentElement.scrollTop;
不过可以使用offsetParent来优化,减少引用深度,简化为:
this .offsetParent.scrollTop;

    那么被锁定的行的完整css就因该是:
< tr  style ="position: relative; top: expression(this.offsetParent.scrollTop);" ></ tr >

    这么简单啊?就这么简单,不过问题当然还是有啦。这样的锁定效果有两个主要的问题:一是表格背景由于默认是透明的,所以如果真的滚动起来,字是不动了,不过都是镂空的重叠效果。解决办法很简单,就是给tr设置上背景颜色就可以啦。第二个问题,比较郁闷,搞了很久才在别人的帮助下搞定。当tr的position为relative后,这个tr里面的td的border属性就貌似失效了,就是不管设置什么颜色,死活都显示不出来:
    TdBorderEmpty.png
    后来在 putee同学的帮助下,发现原来需要把tr中的每个td的position属性也都设置成relative,border才能显示出来!

    搞定了上面的表头,我们再来搞左边的表头。左边原理和上面一样,只是被expression控制的元素是td而不是tr啦。expression中引用div的代码就以该是:
this .parentElement.parentElement.parentElement.parentElement.scrollTop;
比锁定tr多了一个层次的引用,这是使用offsetParent来优化和tr还不同,tr的offsetParent就是容器div;而td的offsetParent还是td,晕!所以要用this.parentElement来取offsetParent,不过这时取到的又是table,再次晕。所以这个优化只能减少一个parent层次的引用,优化为:
this .parentElement.offsetParent.parentElement.scrollTop;

    那么被锁定的列的完整css就因该是:
< td  style ="position: relative; left: expression(this.parentElement.offsetParent.parentElement.scrollTop);" ></ tr >


    搞定了横纵两个方向表头的锁定,结果去发现表头的单元格的边框不太对劲,怎么都是双倍的边线呢?我已经设置了table-collapse为collapse,而且单元格的border设置为solid 1px blue。结果发现这又是position设成了relative后带来的问题,解决办法是只给每个表头单元格设置border的两个边,比如top和left或者right和bottom。下图是表头单元格两种不同border样式设置的效果:     
    
    最后就是Grid左上角那个相对于容器div静止的部分,当然这个部分的tr和td除了需要同时包含上面说到的锁定行表头和列表头的css expression外,还有一个问题就是这个部分的单元格的zIndex必须是表格两个表头中最大的,才能保证不管真么滚动表头,始终能显示这个部分。另外又是由于IE的问题,我们不能把左上角这个部分通过colspan和rowspan合并成一个td,如果合并那么除了第一行外的其行,将在表头滚动时被覆盖掉。所以这个部分的每一行仍然是一个单独的td,只是在水平方向上作了合并优化。

    btw: 由于firefox连td的position为relative都不支持,所以没有任何必要讨论对firefox的支持

 

 

新增一个例子也是从网上弄来的,感觉非常好。

<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ page contentType="text/html; charset=GBK" %>
<html>

	<head>



		<style type="text/css"> 

<!-- 

body,table, td, a { 

font:9pt; 

} 

 

/*重点:固定行头样式*/

.scrollRowThead 

{

     position: relative; 

     left: expression(this.parentElement.parentElement.parentElement.parentElement.scrollLeft);

     z-index:0;

}

 

/*重点:固定表头样式*/

.scrollColThead {

     position: relative; 

     top: expression(this.parentElement.parentElement.parentElement.scrollTop);

     z-index:2;

}

 

/*行列交叉的地方*/

.scrollCR {

     z-index:3;

} 

 

/*div外框*/

.scrollDiv {

height:200px;

clear: both; 

border: 1px solid #EEEEEE;

OVERFLOW: scroll;

width: 100%; 

}

 

/*行头居中*/

.scrollColThead td,.scrollColThead th

{

     text-align: center ;

}

 

 

/*行头列头背景*/

.scrollRowThead,.scrollColThead td,.scrollColThead th

{

background-color:EEEEEE;

}

 

 

 

 

/*表格的线*/

.scrolltable

{

border-bottom:1px solid #CCCCCC; 

border-right:1px solid #CCCCCC; 

}

/*单元格的线等*/

.scrolltable td,.scrollTable th

{

     border-left: 1px solid #CCCCCC; 

     border-top: 1px solid #CCCCCC; 

     padding: 5px; 

}

 

--> 

</style>

		<script>

     

</script>

	</head>
	<body>



		<div id="scrollDiv" class="scrollDiv">

			<table border="0" cellpadding="3" cellspacing="0" width="100%"
				class="scrollTable">



				<tr class="scrollColThead">

					<th class="scrollRowThead scrollCR">
						 
					</th>

					<th colspan="2">
						列头
					</th>

					<th colspan="10">
						列头
					</th>

				</tr>

				<tr class="scrollColThead">

					<th class="scrollRowThead scrollCR">
						h1
					</th>

					<th>
						h2
					</th>

					<th>
						h3
					</th>

					<th>
						h4
					</th>

					<th>
						h5
					</th>

					<th>
						565656
					</th>

					<th>
						565656
					</th>

					<th>
						5656565656
					</th>

					<th>
						56565656
					</th>

					<th>
						56565656
					</th>

					<th>
						56565656
					</th>

					<th>
						56565656
					</th>

					<th>
						56566666666666666666666666666666666666666666666666666666666666666666565656
					</th>

				</tr>

				<tr>

					<td class="scrollRowThead">
						<input type="checkbox" name="checkbox" value="checkbox">

						a
					</td>

					<td>
						单元格2
					</td>

					<td>
						单元格3
					</td>

					<td>
						单元格4
					</td>

					<td>
						单元格5
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

				</tr>

				<tr>

					<td class="scrollRowThead">
						<input type="checkbox" name="checkbox2" value="checkbox">

						b
					</td>

					<td>
						单元格2
					</td>

					<td>
						单元格3
					</td>

					<td>
						单元格4
					</td>

					<td>
						单元格5
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

				</tr>

				<tr>

					<td nowrap class="scrollRowThead">
						<input type="checkbox" name="checkbox3" value="checkbox">

						1
					</td>

					<td nowrap>
						单元格2
					</td>

					<td nowrap>
						单元格3
					</td>

					<td nowrap>
						单元格4
					</td>

					<td nowrap>
						单元格5
					</td>

					<td nowrap>
						 
					</td>

					<td nowrap>
						 
					</td>

					<td nowrap>
						 
					</td>

					<td nowrap>
						 
					</td>

					<td nowrap>
						 
					</td>

					<td nowrap>
						 
					</td>

					<td nowrap>
						 
					</td>

					<td nowrap>
						 
					</td>

				</tr>

				<tr>

					<td class="scrollRowThead">
						<input type="checkbox" name="checkbox4" value="checkbox">

						2
					</td>

					<td>
						单元格2
					</td>

					<td>
						单元格3
					</td>

					<td>
						单元格4
					</td>

					<td>
						单元格5
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

				</tr>

				<tr>

					<td class="scrollRowThead">
						<input type="checkbox" name="checkbox5" value="checkbox">

						3
					</td>

					<td>
						单元格2
					</td>

					<td>
						单元格3
					</td>

					<td>
						单元格4
					</td>

					<td>
						单元格5
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

				</tr>

				<tr>

					<td class="scrollRowThead">
						<input type="checkbox" name="checkbox6" value="checkbox">

						4
					</td>

					<td>
						单元格2
					</td>

					<td>
						单元格3
					</td>

					<td>
						单元格4
					</td>

					<td>
						单元格5
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

				</tr>

				<tr>

					<td class="scrollRowThead">
						<input type="checkbox" name="checkbox7" value="checkbox">

						5
					</td>

					<td>
						单元格2
					</td>

					<td>
						单元格3
					</td>

					<td>
						单元格4
					</td>

					<td>
						单元格5
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

					<td>
						 
					</td>

				</tr>

			</table>

		</div>



	</body>
</html>




 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值