【问题标题】:Fixed table header on window scroll修复了窗口滚动上的表头
【发布时间】:2018-05-23 04:17:36
【问题描述】:

我有一个包含很多行的简单 Bootstrap 表。 有没有办法在滚动窗口时固定表格标题,但让每个列标题的宽度等于文本最多的行的宽度。 因为当将表头位置设置为固定时,表头不会根据内容改变其宽度。 换句话说,根据列中最宽的值(标题中的标题或单元格中的值)设置每列的宽度。 有没有办法将这样的计算放在标题列宽上? 我想不出任何其他方法来做到这一点。 我正在使用角度。

这是我在将标题行的位置设置为固定时尝试过的一个 jsfiddle:JsFiddle 正如您现在所看到的,这些列与正文中的相应列不对齐。 我需要它们对齐,但没有为每一列设置固定宽度,因为我不知道我得到的数据会有多长。

HTML 代码:

<div class="col-md-12 tableDiv"  >
 <table class="table table-striped" >
  <thead class="table-bordered">
    <tr>
      <th>Column1</th>
      <th>Column2</th>
      <th>Column3</th>
      <th>Column4</th>
      <th>Column5</th>
      <th>Column6</th>

    </tr>
  </thead>
  <tbody >
    <tr>
      <td > FIRST</td>
      <td >asdasdfasf</td>
      <td >fsdf</td>
      <td>sdfsfd</td>
      <td>sdfs</td>
      <td>fsdfsdf</td>
    </tr>
        <tr>
      <td > asdf</td>
      <td >asdfa</td>
      <td >fsdf</td>
      <td>sdfsfd</td>
      <td>sdfs</td>
      <td>fsdfsdf</td>
    </tr>
        <tr>
      <td > asdf</td>
      <td >asdfa</td>
      <td >fsdf</td>
      <td>sdfsfd</td>
      <td>sdfs</td>
      <td>fsdfsdf</td>
    </tr>
  </tbody>
</table>
  </div>
<div>
</div>

CSS:

.table-bordered tr {
  position: fixed;
   z-index:1;
  top: 50px;
  background: #fff;
 }

【问题讨论】:

  • 这个问题非常广泛,从某种意义上说,它取决于很多因素,什么可行,什么不可行。发布一些您迄今为止尝试过的代码或 jsfiddle 会更有帮助。
  • 谢谢。我确实添加了代码和额外的解释:)

标签: angular css bootstrap-4


【解决方案1】:

如果你不关心性能并且你可以在标题中没有边框(因为边框不会得到CSS 转换),有一个使用CSS3 转换的解决方案。该技术是获取窗口的滚动并将转换应用于具有相同值的标题。这样,header 就不固定了,保持原来的宽度:

let header = document.querySelector(".table-bordered");
let body = document.body;

function setTranslate (element, value) {
    let style = `translateY(${value}px)`;
    element.style.oTransform = style;
    element.style.MozTransform = style;
    element.style.WebkitTransform = style;
    element.style.transform = style;
}

window.onscroll = () => {
    setTranslate(header, window.scrollY);
};

jsFiddle working example

这个解决方案的坏处是你需要在每个滚动事件中更新标题的样式,所以性能不够好。另一种解决方案是构建两个不同的表,一个用于表头,另一个用于正文,以及一个设置表头宽度的通用函数,同时考虑正文的宽度。这样,您可以在fixed 中设置表格的position 属性,并且您可以在每次调整窗口大小或在需要刷新表格大小的每个时刻调用该函数。看下sn-p:

let header = document.querySelector(".table-header");
let body = document.querySelector(".table-body");
let htds = header.querySelectorAll("th");
let btds = body.querySelectorAll("tbody tr:first-child td");

function fixHeaderWidths() {
  header.style.width = `${body.offsetWidth}px`;
  Array.prototype.forEach.call(htds, (td, index) => {
    td.style.width = `${btds[index].offsetWidth}px`;
  });
  body.style.top = "";
  let top = (header.getBoundingClientRect()).bottom - (btds[0].getBoundingClientRect()).top;
  body.style.top = `${top}px`;
}

fixHeaderWidths();

window.onresize = fixHeaderWidths;
.table-header {
  background: white;
  position: fixed;
  table-layout: fixed;
  z-index: 1;
}

.table-body {
  position: relative;
}

.table-body thead {
  visibility: hidden;
}

.tableDiv {
  margin-top: 40px
}
<link href="https://maxcdn.bootstrapcdn.com/bootswatch/3.3.7/flatly/bootstrap.min.css" rel="stylesheet" />
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.2/css/bootstrap.min.css" rel="stylesheet" />
<div class="col-md-12 tableDiv">
  <table class="table-header table table-stripedcf table-bordered">
    <thead>
      <tr>
        <th>Column1</th>
        <th>Column2</th>
        <th>Column3</th>
        <th>Column4</th>
        <th>Column5</th>
        <th>Column6</th>
      </tr>
    </thead>
  </table>
  <table class="table-body table table-stripedcf table-bordered">
    <thead>
      <tr>
        <th>Column1</th>
        <th>Column2</th>
        <th>Column3</th>
        <th>Column4</th>
        <th>Column5</th>
        <th>Column6</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>FIRST</td>
        <td>asda sdfasf</td>
        <td>fsdf</td>
        <td>sdfsfd</td>
        <td>sdfs</td>
        <td>fsdfsdf</td>
      </tr>
      <tr>
        <td>asdf</td>
        <td>asdfa</td>
        <td>fsdf</td>
        <td>sdfsfd</td>
        <td>sdfs</td>
        <td>fsdfsdf</td>
      </tr>
      <tr>
        <td>asdf</td>
        <td>asdfa</td>
        <td>fsdf</td>
        <td>sdfsfd</td>
        <td>sdfs</td>
        <td>fsdfsdf</td>
      </tr>
      <tr>
        <td>asdf</td>
        <td>asdfa</td>
        <td>fsdf</td>
        <td>sdfsfd</td>
        <td>sdfs</td>
        <td>fsdfsdf</td>
      </tr>
      <tr>
        <td>asdf</td>
        <td>asdfa</td>
        <td>fsdf</td>
        <td>sdfsfd</td>
        <td>sdfs</td>
        <td>fsdfsdf</td>
      </tr>
      <tr>
        <td>asdf</td>
        <td>asdfa</td>
        <td>fsdf</td>
        <td>sdfsfd</td>
        <td>sdfs</td>
        <td>fsdfsdf</td>
      </tr>
      <tr>
        <td>asdf</td>
        <td>asdfa</td>
        <td>fsdf</td>
        <td>sdfsfd</td>
        <td>sdfs</td>
        <td>fsdfsdf</td>
      </tr>
      <tr>
        <td>asdf</td>
        <td>asdfa</td>
        <td>fsdf</td>
        <td>sdfsfd</td>
        <td>sdfs</td>
        <td>fsdfsdf</td>
      </tr>
      <tr>
        <td>asdf</td>
        <td>asdfa</td>
        <td>fsdf</td>
        <td>sdfsfd</td>
        <td>sdfs</td>
        <td>fsdfsdf</td>
      </tr>
      <tr>
        <td>asdf</td>
        <td>asdfa</td>
        <td>fsdf</td>
        <td>sdfsfd</td>
        <td>sdfs</td>
        <td>fsdfsdf</td>
      </tr>
      <tr>
        <td>asdf</td>
        <td>asdfa</td>
        <td>fsdf</td>
        <td>sdfsfd</td>
        <td>sdfs</td>
        <td>fsdfsdf</td>
      </tr>
      <tr>
        <td>asdf</td>
        <td>asdfa</td>
        <td>fsdf</td>
        <td>sdfsfd</td>
        <td>sdfs</td>
        <td>fsdfsdf</td>
      </tr>
      <tr>
        <td>asdf</td>
        <td>asdfa</td>
        <td>fsdf</td>
        <td>sdfsfd</td>
        <td>sdfs</td>
        <td>fsdfsdf</td>
      </tr>
      <tr>
        <td>asdf</td>
        <td>asdfa</td>
        <td>fsdf</td>
        <td>sdfsfd</td>
        <td>sdfs</td>
        <td>fsdfsdf</td>
      </tr>
      <tr>
        <td>asdf</td>
        <td>asdfa</td>
        <td>fsdf</td>
        <td>sdfsfd</td>
        <td>sdfs</td>
        <td>fsdfsdf</td>
      </tr>
      <tr>
        <td>asdf</td>
        <td>asdfa</td>
        <td>fsdf</td>
        <td>sdfsfd</td>
        <td>sdfs</td>
        <td>fsdfsdf</td>
      </tr>
      <tr>
        <td>asdf</td>
        <td>asdfa</td>
        <td>fsdf</td>
        <td>sdfsfd</td>
        <td>sdfs</td>
        <td>fsdfsdf</td>
      </tr>
      <tr>
        <td>asdf</td>
        <td>asdfa</td>
        <td>fsdf</td>
        <td>sdfsfd</td>
        <td>sdfs</td>
        <td>fsdfsdf</td>
      </tr>
      <tr>
        <td>asdf</td>
        <td>asdfa</td>
        <td>fsdf</td>
        <td>sdfsfd</td>
        <td>sdfs</td>
        <td>fsdfsdf</td>
      </tr>
      <tr>
        <td>asdf</td>
        <td>asdfa</td>
        <td>fsdf</td>
        <td>sdfsfd</td>
        <td>sdfs</td>
        <td>fsdfsdf</td>
      </tr>
      <tr>
        <td>asdf</td>
        <td>asdfa</td>
        <td>fsdf</td>
        <td>sdfsfd</td>
        <td>sdfs</td>
        <td>fsdfsdf</td>
      </tr>
      <tr>
        <td>asdf</td>
        <td>asdfa</td>
        <td>fsdf</td>
        <td>sdfsfd</td>
        <td>sdfs</td>
        <td>fsdfsdf</td>
      </tr>
      <tr>
        <td>asdf</td>
        <td>asdfa</td>
        <td>fsdf</td>
        <td>sdfsfd</td>
        <td>sdfs</td>
        <td>fsdfsdf</td>
      </tr>
      <tr>
        <td>asdf</td>
        <td>asdfa</td>
        <td>fsdf</td>
        <td>sdfsfd</td>
        <td>sdfs</td>
        <td>fsdfsdf</td>
      </tr>
      <tr>
        <td>asdf</td>
        <td>asdfa</td>
        <td>fsdf</td>
        <td>sdfsfd</td>
        <td>sdfs</td>
        <td>fsdfsdf</td>
      </tr>
      <tr>
        <td>asdf</td>
        <td>asdfa</td>
        <td>fsdf</td>
        <td>sdfsfd</td>
        <td>sdfs</td>
        <td>fsdfsdf</td>
      </tr>
      <tr>
        <td>asdf</td>
        <td>asdfa</td>
        <td>fsdf</td>
        <td>sdfsfd</td>
        <td>sdfs</td>
        <td>fsdfsdf</td>
      </tr>
      <tr>
        <td>asdf</td>
        <td>asdfa</td>
        <td>fsdf</td>
        <td>sdfsfd</td>
        <td>sdfs</td>
        <td>fsdfsdf</td>
      </tr>
      <tr>
        <td>asdf</td>
        <td>asdfa</td>
        <td>fsdf</td>
        <td>sdfsfd</td>
        <td>sdfs</td>
        <td>fsdfsdf</td>
      </tr>
      <tr>
        <td>asdf</td>
        <td>asdfa</td>
        <td>fsdf</td>
        <td>sdfsfd</td>
        <td>sdfs</td>
        <td>fsdfsdf</td>
      </tr>
      <tr>
        <td>asdf</td>
        <td>asdfa</td>
        <td>fsdf</td>
        <td>sdfsfd</td>
        <td>sdfs</td>
        <td>fsdfsdf</td>
      </tr>
      <tr>
        <td>asdf</td>
        <td>asdfa</td>
        <td>fsdf</td>
        <td>sdfsfd</td>
        <td>sdfs</td>
        <td>fsdfsdf</td>
      </tr>
    </tbody>
  </table>
</div>

如果您不想使用jQuery,请不要使用Bootstrap 脚本文件(我已经看到您已将其包含在您的jsFiddle 中),因为它需要jQuery 才能工作。但是你可以用this之类的东西来替换它。

【讨论】:

  • 谢谢,但我不应该在表格主体内滚动。使它变得困难的是,在窗口滚动时,表头应该保持固定。并且不能使用 Jquery,因为它不能很好地与 Angular 融合。这就是为什么我问是否有办法隐藏实际的thead(根据内容获取宽度的那个)和一个固定的表格标题,其列宽将等于隐藏标题的列宽。
  • @JenPen lkjk,让我试试,我会更新答案
  • 非常感谢。唯一需要的是不手动设置的固定标题的宽度。因为它应该根据该列的行而改变。当它没有固定时,它通常会这样做。谢谢你的尝试!欣赏!
  • 非常感谢您的详尽解释。但是第二个示例效果不佳,因为当其标题的宽度比其各自行中的内容长时,它们会重叠并且不能很好地对齐。
  • @JenPenlkjk 这些技术旨在让您了解可以采用哪种方法。如果您的标题的文本比您的内容长,在这种情况下,您需要执行相反的操作:将宽度设置为您的正文 tds,同时考虑您的标题 ths 的宽度。因此,只需一个简单的条件来执行一种或其他方法就足够了。
猜你喜欢
  • 1970-01-01
  • 2020-07-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-16
  • 1970-01-01
相关资源
最近更新 更多