简体   繁体   English

带有固定(冻结)列和标题的HTML表

[英]HTML table with fixed (frozen) columns and headers

I've been searching over the web for the way to make a table with fixed (frozen) columns and header. 我一直在网上搜索制作带有固定(冻结)列和标题的表的方法。 Seems like I finally found the solution and modified it to my needs. 好像我终于找到了解决方案并根据我的需要进行了修改。

There original fiddle is here . 有原来的小提琴是在这里

Here is my modified solution. 是我修改过的解决方案。 I tested it in Chrome (version: 55.0.2883.87 m) and Firefox (version: 51.0.1). 我在Chrome(版本:55.0.2883.87 m)和Firefox(版本:51.0.1)中测试了它。

The problem is that it works not completely in IE (version: 11.0.9600.18427). 问题是它在IE中不完全有效(版本:11.0.9600.18427)。 During the horizontal scrolling a frozen part of the header is getting scrolled too. 在水平滚动期间,标题的冻结部分也会滚动。 Could someone help me to make it working in IE? 有人可以帮助我让它在IE中工作吗? And one more question: is the approach safe to use? 还有一个问题:这种方法可以安全使用吗? I mean if it's using some unspecified behavior, then some of the future browsers or even some of the modern browsers might display my table in a wrong way, and it's better to use a safe solution with a few different tables and synchronizing scroll position and rows height. 我的意思是如果它使用一些未指定的行为,那么一些未来的浏览器甚至一些现代浏览器可能以错误的方式显示我的表,并且最好使用具有几个不同表的安全解决方案并同步滚动位置和行高度。 UPD: one more question: how to make this work stable on the mobile devices? UPD:还有一个问题:如何在移动设备上保持稳定?

Here is some code that demonstrates the approach: 以下是一些演示该方法的代码:

 $(document).ready(function() { $('tbody').scroll(function(e) { //detect a scroll event on the tbody /* Setting the thead left value to the negative valule of tbody.scrollLeft will make it track the movement of the tbody element. Setting an elements left value to that of the tbody.scrollLeft left makes it maintain it's relative position at the left of the table. */ $('thead').css("left", -$("tbody").scrollLeft()); //fix the thead relative to the body scrolling $('thead th:nth-child(1)').css("left", $("tbody").scrollLeft()); //fix the first cell of the header $('tbody td:nth-child(1)').css("left", $("tbody").scrollLeft()); //fix the first column of tdbody }); }); 
 .container { height:200px; width:400px; overflow: hidden; } table { position: relative; background-color: #aaa; border-collapse: collapse; table-layout: fixed; display: flex; flex-direction: column; height: 100%; width: 100%; } /*thead*/ thead { position: relative; display: block; /*seperates the header from the body allowing it to be positioned*/ } thead th { background-color: #99a; min-width: 120px; border: 1px solid #222; } thead th:nth-child(1) {/*first cell in the header*/ position: relative; background-color: #88b; } /*tbody*/ tbody { flex: 1; position: relative; display: block; /*seperates the tbody from the header*/ overflow: auto; } tbody td { background-color: #bbc; min-width: 120px; border: 1px solid #222; } tbody tr td:nth-child(1) { /*the first cell in each tr*/ position: relative; background-color: #99a; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <body> <div class="container"> <table> <thead> <tr> <th>Name<br/>123</th> <th>Town</th> <th>County</th> <th>Age</th> <th>Profession</th> <th>Anual Income</th> <th>Matital Status</th> <th>Children</th> </tr> <tr> <th>Name</th> <th>Town</th> <th>County</th> <th>Age<br/>123<br/>321</th> <th>Profession</th> <th>Anual Income</th> <th>Matital Status</th> <th>Children</th> </tr> </thead> <tbody> <tr> <td>John Smith</td> <td>Macelsfield</td> <td>Cheshire<br/>123</td> <td>52</td> <td>Brewer</td> <td>£47,000</td> <td>Married</td> <td>2</td> </tr> <tr> <td>Jenny Jones<br/>123<br/>312</td> <td>Threlkeld</td> <td>Cumbria</td> <td>34</td> <td>Shepherdess</td> <td>£28,000</td> <td>Single</td> <td>0</td> </tr> <tr> <td>Peter Frampton</td> <td>Avebury</td> <td>Wiltshire</td> <td>57</td> <td>Musician</td> <td>£124,000</td> <td>Married</td> <td>4</td> </tr> <tr> <td>Simon King</td> <td>Malvern</td> <td>Worchestershire</td> <td>48</td> <td>Naturalist</td> <td>£65,000</td> <td>Married</td> <td>2</td> </tr> <tr> <td>Lucy Diamond</td> <td>St Albans</td> <td>Hertfordshire</td> <td>67</td> <td>Pharmasist</td> <td>Retired</td> <td>Married</td> <td>3</td> </tr> <tr> <td>Austin Stevenson</td> <td>Edinburgh</td> <td>Lothian </td> <td>36</td> <td>Vigilante</td> <td>£86,000</td> <td>Single</td> <td>Unknown</td> </tr> <tr> <td>Wilma Rubble</td> <td>Bedford</td> <td>Bedfordshire</td> <td>43</td> <td>Housewife</td> <td>N/A</td> <td>Married</td> <td>1</td> </tr> <tr> <td>Kat Dibble</td> <td>Manhattan</td> <td>New York</td> <td>55</td> <td>Policewoman</td> <td>$36,000</td> <td>Single</td> <td>1</td> </tr> <tr> <td>Henry Bolingbroke</td> <td>Bolingbroke</td> <td>Lincolnshire</td> <td>45</td> <td>Landowner</td> <td>Lots</td> <td>Married</td> <td>6</td> </tr> <tr> <td>Alan Brisingamen</td> <td>Alderley</td> <td>Cheshire</td> <td>352</td> <td>Arcanist</td> <td>A pile of gems</td> <td>Single</td> <td>0</td> </tr> </tbody> </table> </div> </body> 

This is very peculiar. 这非常奇特。 It appears that the problematic code is this line: 似乎有问题的代码是这一行:

$('thead').css("left", -$("tbody").scrollLeft()); //fix the thead relative to the body scrolling

It looks like IE11 handles relative positioning of nested elements differently (than Chrome and other browsers). 看起来IE11处理嵌套元素的相对位置(与Chrome和其他浏览器不同)。 In this case, you are positioning thead with relative positioning with an offset. 在这种情况下,您将使用偏移相对定位来定位thead You are also positioning thead th (it's children) with an offset and relative positioning. 您也定位thead th (它的儿童)的偏移和相对定位。 Chrome appears to be positioning thead relative to table , and then positioning th relative to thead . 铬似乎定位thead相对于table ,然后定位th相对于thead IE11, on the other hand, appears to be positioning thead relative to table , and then th just inherits that same positioning regardless of its own positioning. IE11,在另一方面,似乎被定位thead相对于table ,然后th刚刚继承了相同的定位,无论其自身的定位。

A fix for this would be the following: on IE11, handle the positioning differently for thead . 对此的修复如下:在IE11上,为thead处理不同的定位。 Instead of setting the positioning on the parent thead , set the positioning on the thead th elements. 而不是设置在父的定位thead ,设置在所述定位thead th元素。 In that way, your first column will not be 'forced' to inherit thead 's positioning (in IE). 这样一来,你的第一个栏就不会被“逼”继承thead的定位(在IE)。

$(document).ready(function() {
  var isIE11 = !!navigator.userAgent.match(/Trident.*rv\:11\./);
  var customScroller;
  if (isIE11)
    customScroller = function() {
      $('thead th').css("left", -$("tbody").scrollLeft()); //if using IE11, fix the th element 
    };
  else
    customScroller = function() {
      $('thead').css("left", -$("tbody").scrollLeft()); //if not using IE11, fix the thead element
    };

  $('tbody').scroll(function(e) { //detect a scroll event on the tbody
    /*
    Setting the thead left value to the negative valule of tbody.scrollLeft will make it track the movement
    of the tbody element. Setting an elements left value to that of the tbody.scrollLeft left makes it maintain             it's relative position at the left of the table.    
    */
    customScroller(); //fix the thead relative to the body scrolling
    $('thead th:nth-child(1)').css("left", $("tbody").scrollLeft());
//fix the first cell of the header
    $('tbody td:nth-child(1)').css("left", $("tbody").scrollLeft()); //fix the first column of tdbody
  });
});

Here is a full example with your code, showing different handlings based on the browser: 以下是您的代码的完整示例,显示基于浏览器的不同处理:

https://jsfiddle.net/8tx4xfhx/5/ https://jsfiddle.net/8tx4xfhx/5/

Alsol, it would be nice to see if anyone has noticed this behavior before. Alsol,很高兴看到之前是否有人注意过这种行为。 It appears that IE11 handles nested relative positioning differently than other browsers. 看来IE11处理嵌套相对定位的方式与其他浏览器不同。 Is there a spec somewhere that defines what the standard should be? 是否有某个规范定义了标准应该是什么? Should relative positioning be inherited like IE does it? 应该像IE一样继承相对定位吗? Or should relative positioning always be relative to the parent? 或者相对定位是否总是相对于父母? I would think the latter. 我会想到后者。 But performance considerations must also be taken. 但是还必须考虑性能因素。

You should try below code sample with reference of jquery.floatThead.js. 您应该参考jquery.floatThead.js尝试下面的代码示例。

                    var $demoTable = $("div.table-responsive table");
                    $demoTable.floatThead({
                        top: 200,
                        scrollContainer: function ($table) {                                
                            return $table.closest('.table-responsive');
                        },
                        position: 'absolute'
                    });

you need to get the reference of jquery.floatThead.js file and try to apply this on table. 你需要获取jquery.floatThead.js文件的引用并尝试在表上应用它。

You can check this working on below link. 您可以通过以下链接查看此信息。 http://mkoryak.github.io/floatThead/ http://mkoryak.github.io/floatThead/

Generally for frozen rows & columns, I always prefer to use a css-only solution for best browser-compatibility. 通常对于冻结的行和列,我总是更喜欢使用仅限css的解决方案以获得最佳的浏览器兼容性。

I have tried to replicate your code here with a css-only solution. 我试图用css-only解决方案在这里复制你的代码。

I am working on a mac, so don't have access to IE. 我正在使用mac,因此无法访问IE。 Please verify if its working fine on the same. 请验证它是否正常工作。

Updated fiddle: https://jsfiddle.net/nashcheez/bzuasLcz/81/ 更新小提琴: https//jsfiddle.net/nashcheez/bzuasLcz/81/

Refer code: 参考代码:

 table { position: relative; width: 700px; background-color: #aaa; overflow: hidden; border-collapse: collapse; } /*thead*/ thead { position: relative; display: block; /*seperates the header from the body allowing it to be positioned*/ width: 700px; overflow: visible; } thead th { background-color: #99a; min-width: 120px; height: 36px; min-height: 36px; border: 1px solid #222; } thead th:nth-child(1) { /*first cell in the header*/ position: relative; display: block; background-color: #88b; } tbody tr td:nth-child(2) { margin-left: 124px; display: block; } /*tbody*/ tbody { display: block; width: 700px; height: 239px; overflow-y: auto; } tbody td { background-color: #bbc; min-width: 120px; border: 1px solid #222; height: 36px; min-height: 36px; } tbody tr td:nth-child(1) { /*the first cell in each tr*/ position: absolute; display: inline-block; background-color: #99a; } 
 <body> <table> <thead> <tr> <th>Name</th> <th>Town</th> <th>County</th> <th>Age</th> <th>Profession</th> <th>Anual Income</th> <th>Matital Status</th> <th>Children</th> </tr> </thead> <tbody> <tr> <td>John Smith</td> <td>Macelsfield</td> <td>Cheshire</td> <td>52</td> <td>Brewer</td> <td>£47,000</td> <td>Married</td> <td>2</td> </tr> <tr> <td>Jenny Jones</td> <td>Threlkeld</td> <td>Cumbria</td> <td>34</td> <td>Shepherdess</td> <td>£28,000</td> <td>Single</td> <td>0</td> </tr> <tr> <td>Peter Frampton</td> <td>Avebury</td> <td>Wiltshire</td> <td>57</td> <td>Musician</td> <td>£124,000</td> <td>Married</td> <td>4</td> </tr> <tr> <td>Simon King</td> <td>Malvern</td> <td>Worchestershire</td> <td>48</td> <td>Naturalist</td> <td>£65,000</td> <td>Married</td> <td>2</td> </tr> <tr> <td>Lucy Diamond</td> <td>St Albans</td> <td>Hertfordshire</td> <td>67</td> <td>Pharmasist</td> <td>Retired</td> <td>Married</td> <td>3</td> </tr> <tr> <td>Austin Stevenson</td> <td>Edinburgh</td> <td>Lothian</td> <td>36</td> <td>Vigilante</td> <td>£86,000</td> <td>Single</td> <td>Unknown</td> </tr> <tr> <td>Wilma Rubble</td> <td>Bedford</td> <td>Bedfordshire</td> <td>43</td> <td>Housewife</td> <td>N/A</td> <td>Married</td> <td>1</td> </tr> <tr> <td>Kat Dibble</td> <td>Manhattan</td> <td>New York</td> <td>55</td> <td>Policewoman</td> <td>$36,000</td> <td>Single</td> <td>1</td> </tr> <tr> <td>Henry Bolingbroke</td> <td>Bolingbroke</td> <td>Lincolnshire</td> <td>45</td> <td>Landowner</td> <td>Lots</td> <td>Married</td> <td>6</td> </tr> <tr> <td>Alan Brisingamen</td> <td>Alderley</td> <td>Cheshire</td> <td>352</td> <td>Arcanist</td> <td>A pile of gems</td> <td>Single</td> <td>0</td> </tr> </tbody> </table> </body> 

The problem is that IE does not allow one to adjust the left attribute of a cell in a row independent from the row as a whole. 问题是IE不允许人们独立于行整体调整行中单元格的left属性。 We can see this by editing the DOM directly using the developer window in IE and the developer window in Chrome. 我们可以通过使用IE中的开发人员窗口和Chrome中的开发人员窗口直接编辑DOM来看到这一点。

In Chrome, when you scroll left and right, you can see in the Element viewer that the left attribute is changed on the element itself, which overrides all CSS. 在Chrome中,当您向左和向右滚动时,您可以在元素查看器中看到元素本身的left属性已更改,这将覆盖所有CSS。 We can reload the page and set the element attribute manually in this same screen: style:'left:300px' , and we will see the header cell move to the right 300px and hover over the remaining header cells. 我们可以重新加载页面并在同一屏幕中手动设置元素属性: style:'left:300px' ,我们将看到标题单元格向右移动300px并将鼠标悬停在剩余的标题单元格上。 This is good behavior and the behavior that makes this method work. 这是良好的行为和使该方法有效的行为。

If we do the same thing in IE and add style: 'left:300px' to the th element, we will see that the cell does not move. 如果我们在IE中做同样的事情并添加style: 'left:300px'到第th个元素,我们将看到单元格不移动。 Nothing we do to the style attributes of that cell will cause it to leave its place in the table. 我们对该单元格的样式属性所做的任何操作都不会导致它在表格中留下它的位置。 It is this 'feature' of IE that is causing the method to fail. IE的这个“功能”导致该方法失败。 IE is insisting on maintaining cell order no matter what attributes are applied to the elements within a row. 无论将哪些属性应用于行内的元素,IE都坚持维护单元格顺序。

The trick is to work around this complication in a way that makes all browsers happy. 诀窍是以一种让所有浏览器都满意的方式解决这个复杂问题。 There are many ways to do this, but I would probably use two tables, and use DIVs to position them so that the edges match. 有很多方法可以做到这一点,但我可能会使用两个表,并使用DIV来定位它们以使边匹配。 I would add javascript so that if one tbody scrolls up or down that it affects the other tbody in the same manner. 我会添加javascript,以便如果一个tbody向上或向下滚动它会以相同的方式影响另一个tbody。 If it scrolls right or left, nothing happens to the first table, which holds your frozen column headers, and the right table moves in the scroll direction as planned. 如果它向右或向左滚动,第一个表没有任何反应,它保存您的冻结列标题,右表按计划在滚动方向上移动。

By using two tables, IE no longer associates the header that you are trying to freeze with the header that is moving. 通过使用两个表,IE不再将您尝试冻结的标头与正在移动的标头相关联。 Careful CSS will disguise your hack and make the table appear as one table. 小心的CSS将伪装你的黑客并使表格显示为一个表格。

Good luck and happy coding! 祝你好运,编码愉快!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM