Table header to stay fixed at the top when user sc

2018-12-31 09:45发布

I am trying to design an HTML table where the header will stay at the top of the page when AND ONLY when the user scrolls it out of view. For example, the table may be 500 pixels down from the page, how do I make it so that if the user scrolls the header out of view (browser detects its no longer in the windows view somehow), it will stay put at the top? Anyone can give me a Javascript solution to this?

<table>
  <thead>
    <tr>
      <th>Col1</th>
      <th>Col2</th>
      <th>Col3</th>
    </tr>
  </thead>
  <tbody>
     <tr>
       <td>info</td>
       <td>info</td>
       <td>info</td>
     </tr>
     <tr>
       <td>info</td>
       <td>info</td>
       <td>info</td>
     </tr>
     <tr>
       <td>info</td>
       <td>info</td>
       <td>info</td>
     </tr>
  </tbody>
</table>

So in the above example, I want the <thead> to scroll with the page if it goes out of view.

IMPORTANT: I am NOT looking for a solution where the <tbody> will have a scrollbar (overflow:auto).

22条回答
流年柔荑漫光年
2楼-- · 2018-12-31 10:40

This can be achieved by using style property transform. All you have to do is wrapping your table into some div with fixed height and overflow set to auto, for example:

.tableWrapper {
  overflow: auto;
  height: calc( 100% - 10rem );
}

And then you can attach onscroll handler to it, here you have method that finds each table wrapped with <div class="tableWrapper"></div>:

  fixTables () {
    document.querySelectorAll('.tableWrapper').forEach((tableWrapper) => {
      tableWrapper.addEventListener('scroll', () => {
        var translate = 'translate(0,' + tableWrapper.scrollTop + 'px)'
        tableWrapper.querySelector('thead').style.transform = translate
      })
    })
  }

And here is working example of this in action (i have used bootstrap to make it prettier): fiddle

For those who also want to support IE and Edge, here is the snippet:

  fixTables () {
    const tableWrappers = document.querySelectorAll('.tableWrapper')
    for (let i = 0, len = tableWrappers.length; i < len; i++) {
      tableWrappers[i].addEventListener('scroll', () => {
        const translate = 'translate(0,' + tableWrappers[i].scrollTop + 'px)'
        const headers = tableWrappers[i].querySelectorAll('thead th')
        for (let i = 0, len = headers.length; i < len; i++) {
          headers[i].style.transform = translate
        }
      })
    }
  }

In IE and Edge scroll is a little bit laggy... but it works

Here is answer which helps me to find out this: answer

查看更多
不再属于我。
3楼-- · 2018-12-31 10:41

Best solution is to use this jquery plugin:

https://github.com/jmosbech/StickyTableHeaders

This plugin worked great for us and we tried a lot other solutions. We tested it in IE, Chrome and Firefox

查看更多
听够珍惜
4楼-- · 2018-12-31 10:42
function fix_table_header_position(){
 var width_list = [];
 $("th").each(function(){
    width_list.push($(this).width());
 });
 $("tr:first").css("position", "absolute");
 $("tr:first").css("z-index", "1000");
 $("th, td").each(function(index){
    $(this).width(width_list[index]);
 });

 $("tr:first").after("<tr height=" + $("tr:first").height() + "></tr>");}

This is my solution

查看更多
笑指拈花
5楼-- · 2018-12-31 10:48

I've tried most of these solutions, and eventually found (IMO) the best, modern, solution:

CSS grids


With CSS grids, you can define a 'grid', and you can finally create a nice, javascript-free, cross-browser solution for a table with a fixed header, and scrollable content. The header height can even dynamic.

CSS: Display as grid, and set the number of template-rows:

.grid {
    display: grid;
    grid-template-rows: 50px auto; // For fixed height header
    grid-template-rows: auto auto; // For dynamic height header
}

HTML: Create a grid container and the number of defined rows:

<div class="grid">
    <div></div>
    <div></div>
</div>

Here is working example:

CSS

body {
  margin: 0px;
  padding: 0px;
  text-align: center;
}

.table {
  width: 100%;
  height: 100%;
  display: grid;
  grid-template-rows: 50px auto;
}
.table-heading {
  background-color: #ffffd;
}
.table-content {
  overflow-x: hidden;
  overflow-y: scroll;
}

HTML

<html>
    <head>
    </head>
    <body>
        <div class="table">
            <div class="table-heading">
                HEADING
            </div>
            <div class="table-content">
                CONTENT - CONTENT - CONTENT <br/>
                CONTENT - CONTENT - CONTENT <br/>
                CONTENT - CONTENT - CONTENT <br/>
                CONTENT - CONTENT - CONTENT <br/>
                CONTENT - CONTENT - CONTENT <br/>
                CONTENT - CONTENT - CONTENT <br/>
            </div>
        </div>
    </body>
</html>
查看更多
谁念西风独自凉
6楼-- · 2018-12-31 10:49

I wrote a plugin that does this. Ive been working on it for about a year now and I think it handles all the corner cases pretty well:

  • scrolling within a container with overflow
  • scrolling within a window
  • taking care of what happens when you resize the window
  • keeping your events bound to the header
  • most importantly it doesn't force you to change your table's css to make it work

Here are some demos/docs:
http://mkoryak.github.io/floatThead/

查看更多
孤独总比滥情好
7楼-- · 2018-12-31 10:49

Fix your issue with this

tbody {
  display: table-caption;
  height: 200px;
  caption-side: bottom;
  overflow: auto;
}
查看更多
登录 后发表回答