简体   繁体   English

滚动时修复HTML表头

[英]Fixing HTML Table Header while scrolling

I have an HTML table which is quit long, and I need to fix the header from scrolling, I have found many and many of the plugins and tricks to do it, but none worked for me. 我有一个退出很长的HTML表,我需要通过滚动修复标题,我已经找到了很多很多插件和技巧,但没有一个对我有效。

I guessed the reason nothing works for me is due to: 我猜想没有对我有用的原因是由于:

  1. All of the solutions detach the header from the table 所有解决方案都从表中分离了标题
  2. They use fixed width for every column to fit to keep the header on top of the content 它们为每列使用固定宽度以适合将标题保持在内容的顶部
  3. my table is very responsive and stretches to get the full width possible ( width=100% ) 我的表非常敏感,可以拉伸以获得整个宽度( width=100%

Do anybody have a suggestion ? 有人有建议吗?

edit: thanks to ashley I updated my css technics 编辑:感谢ashley我更新了我的css技术

My hmlt table looks exactly like: http://jsfiddle.net/enPZP/4/ 我的hmlt表看起来完全像: http//jsfiddle.net/enPZP/4/

I think I came up with a rather nice solution to the problem, it's a little deeper than I wanted it to be but I'm really happy with the results. 我想我想出了一个相当不错的问题解决方案,它比我想要的要深一点,但我对结果非常满意。

在此输入图像描述

The way it works is on document ready, clones the table header, sets the clone's size to the size of the table header and places it on top of the other header. 它的工作方式是文档就绪,克隆表头,将克隆的大小设置为表头的大小,并将其放在另一个头的顶部。 On scroll if the top of the window is below the top of the table we set the clone's top to be at the top of the window. 滚动时如果窗口顶部低于表格顶部,我们将克隆top设置在窗口顶部。 On resize we recalcuate the <th> sizes. 在调整大小时,我们重新计算<th>大小。

Note that I placed the <th> s into a <thead> separate from the . 请注意,我将<th>放入<thead>中。

jsFiddle 的jsfiddle

var tableBaseTop;
var originalHeader;
var floatingHeader;

$(document).ready(function () {
    tableBaseTop = $('table th').offset().top;
    originalHeader = $('thead');
    floatingHeader = originalHeader.clone();
    floatingHeader
        .css('position', 'absolute')
        .css('top', 0);

    setFloatingHeaderSize();

    $('table').prepend(floatingHeader);

    $(window).scroll(function () {
        var windowTop = $(window).scrollTop();

        if (windowTop > tableBaseTop)
            floatingHeader.css('top', windowTop - tableBaseTop);
        else
            floatingHeader.css('top', 0);
    });

    $(window).resize(setFloatingHeaderSize);
});

function setFloatingHeaderSize() {
    var originalThs = originalHeader.find('th');
    var floatingThs = floatingHeader.find('th');
    for (var i = 0; i < originalThs.length; i++) {
        floatingThs.eq(i)
            .css('width', originalThs.eq(i).width())
            .css('height', originalThs.eq(i).height());
    }
}

Firefox header width problem Firefox标题宽度问题

I managed to fix the problem but I couldn't figure out how to do it using jQuery's helpers. 我设法解决了这个问题,但我无法弄清楚如何使用jQuery的助手来解决这个问题。 The problem was that jQuery was giving me integer sizes when the actual width/height were decimals and I needed them as floats. 问题是,当实际的宽度/高度是小数时,jQuery给了我整数大小,我需要它们作为浮点数。 Here is the section of code that I changed with a working fiddle. 这是我用一个工作小提琴改变的代码部分。

jsFiddle 的jsfiddle

function setFloatingHeaderSize() {
    var originalThs = originalHeader.find('th');
    var floatingThs = floatingHeader.find('th');
    for (var i = 0; i < originalThs.length; i++) {
        var padding = 
            parseFloat(window.getComputedStyle(this.originalThs[i], null).getPropertyValue('padding-left').replace('px', ''), 10) +
            parseFloat(window.getComputedStyle(this.originalThs[i], null).getPropertyValue('padding-right').replace('px', ''), 10);

        floatingThs.eq(i)
            .css('width', this.originalThs[i].offsetWidth - padding)
            .css('height', this.originalThs[i].offsetHeight - padding);
    }
}

Update: I made this in to a reusable library shortly after coming up with the solution, view on GitHub . 更新:我在提出解决方案后立即将其转换为可重用的库, 在GitHub上查看

I have modified your fiddle with this it fixes the Header to the top of the grid. 我已经修改了你的摆弄这个修复该头到网格的顶部。 but it does have a drawback of fixing the tile to the top left. 但它确实有将瓷砖固定在左上方的缺点。

hopefully this will help you on your way to a full answer. 希望这能帮助您获得完整答案。

table {
    width: 100%;
    border-collapse: collapse;
    position: relative;
}
div.scoll {
    overflow: scroll;
    height: 300px;
}
.center {
    text-align: center;
}
thead {
    position: static;
    width: 100%;
}
thead tr {
    position: fixed;
}

and changed you html to look something like 并改变你的HTML看起来像

<div class="scoll">
<table>
        <thead>
            <tr>
                <th>Code</th>
                <th>Rank</th>
                <th>Code</th>
                <th>Icon</th>
                <th>Message Text</th>
                <th>Progress</th>
                <th>Current</th>
                <th>X</th>
                <th>Y</th>
                <th>Z</th>
                <th>W</th>
                <th>Result</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td colspan="12">&nbsp;</td>
            </tr>
            <tr class="data-row" id="19">
                <td class="center">DDD</td>
                <!-- 4 alpha numeric -->
                <td class="center">111</td>
                <!-- 3 digits -->
                <td class="center">222</td>
                <!-- 3 digits -->
                <td class="center">
                    <img width="20" height="20" src="http://cdn1.iconfinder.com/data/icons/CrystalClear/128x128/apps/ark2.png">
                    <!-- icon -->
                </td>
                <td>Lorem ipsum</td>
                <!-- text may be long -->
                <td class="center">333</td>
                <!-- 3 alpha numeric -->
                <td class="center">444</td>
                <!-- 3 alpha numeric -->
                <td class="center">555</td>
                <!-- 3 alpha numeric -->
                <td class="center">666</td>
                <!-- 3 alpha numeric -->
                <td class="center">777</td>
                <!-- 3 alpha numeric -->
                <td class="center">888</td>
                <!-- 3 alpha numeric -->
                <td class="center">999</td>
                <!-- 3 alpha numeric -->
            </tr>
</tbody>
</table>
</div>

Seperate head row to another table and add some jquery code: 将头行分隔到另一个表并添加一些jquery代码:

html: HTML:

<table class="headtable">
<tr>
    <td>name</td>
    <td>value</td>
    <td>action</td>
</tr>
</table>
<div class="scrolltable">
    <table class="valuetable">
        <tr>
            <td>hay 1</td>
            <td>1</td>
            <td>edit</td>
        </tr>
<tr>
            <td>hay 1</td>
            <td>1</td>
            <td>edit</td>
        </tr>
        <tr>
            <td>hay 1</td>
            <td>1</td>
            <td>edit</td>
        </tr>
        <tr>
            <td>hay 1</td>
            <td>1</td>
            <td>edit</td>
        </tr>
        </table>
</div>

js code: js代码:

$('.headtable tr').children().each(function(index)
    {      
      $(this).width($('.valuetable tr:first td').eq(index).width());
    });

style if need: 风格如果需要:

.scrolltable{height:500px; overflow:auto;}

if you want it auto resize (responsitive): 如果你想要它自动调整大小(负责):

$(window).resize(function(){
$('.headtable tr').children().each(function(index)
        {      
          $(this).width($('.valuetable tr:first td').eq(index).width());
        });
});

If fixed- height column headers are acceptable, then this problem can be solved with pure CSS. 如果可以接受固定高度的列标题,则可以使用纯CSS解决此问题。

Here's an example that is configured with a fluid table width and auto column widths, just like the OP's table: jsFiddle 这是一个配置流体表宽度和自动列宽的示例,就像OP的表一样: jsFiddle

Note that the vertical scrollbar only appears when necessary in that example, so you may have to resize the frame to see it. 请注意,垂直滚动条仅在该示例中仅在必要时出现,因此您可能必须调整框架的大小才能看到它。

The code below is the same as the fiddle, but with a fixed table height. 下面的代码与小提琴相同,但具有固定的桌面高度。 The scrollbar always shows in that configuration as long as there are enough rows to exceed the specified height: 只要有足够的行超出指定的高度,滚动条就会始终显示在该配置中:

HTML HTML

<div class="scrollingtable">
  <div>
    <div>
      <table>
        <caption>Top Caption</caption>
        <thead>
          <tr>
            <th><div label="Column 1"/></th>
            <th><div label="Column 2"/></th>
            <th><div label="Column 3"/></th>
            <th>
              <!--more versatile way of doing column label; requires 2 identical copies of label-->
              <div><div>Column 4</div><div>Column 4</div></div>
            </th>
            <th class="scrollbarhead"/> <!--ALWAYS ADD THIS EXTRA CELL AT END OF HEADER ROW-->
          </tr>
        </thead>
        <tbody>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
          <tr><td>Lorem ipsum</td><td>Dolor</td><td>Sit</td><td>Amet consectetur</td></tr>
        </tbody>
      </table>
    </div>
    Faux bottom caption
  </div>
</div>

CSS CSS

<!--[if lte IE 9]><style>.scrollingtable > div > div > table {margin-right: 17px;}</style><![endif]-->
<style>
/*the following html and body rule sets are required only if using a % width or height*/
html {
  width: 100%;
  height: 100%;
}
body {
  box-sizing: border-box;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0 20px 0 20px;
    text-align: center;
}
.scrollingtable {
  box-sizing: border-box;
  display: inline-block;
  vertical-align: middle;
  overflow: hidden;
  width: auto; /*if you want a fixed width, set it here, else set to auto*/
  min-width: /*0*/100%; /*if you want a % width, set it here, else set to 0*/
  height: /*188px*/100%; /*set table height here; can be fixed value or %*/
  min-height: /*0*/104px; /*if using % height, make this large enough to fit scrollbar arrows + caption + thead*/
  font-family: Verdana, Tahoma, sans-serif;
  font-size: 16px;
  line-height: 20px;
  padding: 20px 0 20px 0; /*need enough padding to make room for caption*/
  text-align: left;
}
.scrollingtable * {box-sizing: border-box;}
.scrollingtable > div {
  position: relative;
  border-top: 1px solid black;
  height: 100%;
  padding-top: 20px; /*this determines column header height*/
}
.scrollingtable > div:before {
  top: 0;
  background: cornflowerblue; /*header row background color*/
}
.scrollingtable > div:before,
.scrollingtable > div > div:after {
  content: "";
  position: absolute;
  z-index: -1;
  width: 100%;
  height: 100%;
  left: 0;
}
.scrollingtable > div > div {
  min-height: /*0*/43px; /*if using % height, make this large enough to fit scrollbar arrows*/
  max-height: 100%;
  overflow: /*scroll*/auto; /*set to auto if using fixed or % width; else scroll*/
  overflow-x: hidden;
  border: 1px solid black; /*border around table body*/
}
.scrollingtable > div > div:after {background: white;} /*match page background color*/
.scrollingtable > div > div > table {
  width: 100%;
  border-spacing: 0;
  margin-top: -20px; /*inverse of column header height*/
  margin-right: 17px; /*uncomment if using % width*/
}
.scrollingtable > div > div > table > caption {
  position: absolute;
  top: -20px; /*inverse of caption height*/
  margin-top: -1px; /*inverse of border-width*/
  width: 100%;
  font-weight: bold;
  text-align: center;
}
.scrollingtable > div > div > table > * > tr > * {padding: 0;}
.scrollingtable > div > div > table > thead {
  vertical-align: bottom;
  white-space: nowrap;
  text-align: center;
}
.scrollingtable > div > div > table > thead > tr > * > div {
  display: inline-block;
  padding: 0 6px 0 6px; /*header cell padding*/
}
.scrollingtable > div > div > table > thead > tr > :first-child:before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  height: 20px; /*match column header height*/
  border-left: 1px solid black; /*leftmost header border*/
}
.scrollingtable > div > div > table > thead > tr > * > div[label]:before,
.scrollingtable > div > div > table > thead > tr > * > div > div:first-child,
.scrollingtable > div > div > table > thead > tr > * + :before {
  position: absolute;
  top: 0;
  white-space: pre-wrap;
  color: white; /*header row font color*/
}
.scrollingtable > div > div > table > thead > tr > * > div[label]:before,
.scrollingtable > div > div > table > thead > tr > * > div[label]:after {content: attr(label);}
.scrollingtable > div > div > table > thead > tr > * + :before {
  content: "";
  display: block;
  min-height: 20px; /*match column header height*/
  padding-top: 1px;
  border-left: 1px solid black; /*borders between header cells*/
}
.scrollingtable .scrollbarhead {float: right;}
.scrollingtable .scrollbarhead:before {
  position: absolute;
  width: 100px;
  top: -1px; /*inverse border-width*/
  background: white; /*match page background color*/
}
.scrollingtable > div > div > table > tbody > tr:after {
  content: "";
  display: table-cell;
  position: relative;
  padding: 0;
  border-top: 1px solid black;
  top: -1px; /*inverse of border width*/
}
.scrollingtable > div > div > table > tbody {vertical-align: top;}
.scrollingtable > div > div > table > tbody > tr {background: white;}
.scrollingtable > div > div > table > tbody > tr > * {
  border-bottom: 1px solid black;
  padding: 0 6px 0 6px;
  height: 20px; /*match column header height*/
}
.scrollingtable > div > div > table > tbody:last-of-type > tr:last-child > * {border-bottom: none;}
.scrollingtable > div > div > table > tbody > tr:nth-child(even) {background: gainsboro;} /*alternate row color*/
.scrollingtable > div > div > table > tbody > tr > * + * {border-left: 1px solid black;} /*borders between body cells*/
</style>

The background colors will have to be changed and the borders removed for it to look exactly like the OP's table. 必须更改背景颜色并删除边框,使其看起来与OP的表格完全相同 Instructions for making those types of changes can be found in the CSS comments. 可以在CSS注释中找到进行这些类型更改的说明。

Check my answer here for an alternate configuration, and check d-Pixie's answer in the same post for an explanation of the basic technique used to freeze the header row. 在这里查看我的答案以获得备用配置,并在同一篇文章中查看d-Pixie的答案,以获得用于冻结标题行的基本技术的解释。

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

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