在纯CSS中实现固定表头和固定列的表格

132

我需要创建一个带有固定头部和第一列的HTML表格(或类似外观的表格)。

迄今为止,我看到的每个解决方案都使用JavaScript或jQuery来设置scrollTop/scrollLeft,但在移动浏览器上不够流畅,因此我正在寻找纯CSS解决方案。

我在这里找到了一个解决固定列的方案:jsfiddle.net/C8Dtf/20/,但我不知道如何增强它以使头部也固定。

我希望它能在Webkit浏览器上运行或使用一些CSS3功能,但我再次强调,我不想使用Javascript进行滚动。

编辑: 这是我想要实现的行为示例:https://web.archive.org/web/20130829032141/http://datatables.net/release-datatables/extras/FixedColumns/css_size.html


我目前没有看到 <html> 带有固定标题 <thead> 的 <table> 与 CSS-3 级别有什么关系。你还有什么其他想法?你迄今为止尝试了什么? - Milche Patern
我尝试将复杂的“position”行为应用于行和单元格,但我不太明白它在哪里适用或不适用。 - panfil
2
这个答案可能会对你有所帮助 https://dev59.com/RmUq5IYBdhLWcg3wC8Lx#22801367 - Garry
22个回答

1

在有些困惑后,我刚刚做出了一个解决方案。似乎需要设置一些z-index属性才能使它正常工作,我的解决方案并不完美,但适用于我的应用程序:

CSS的关键(使用SCSS)是首先为非粘性元素设置属性以建立z-index属性。

.wrapper {
position: relative;
white-space: nowrap;
overflow: auto;
height: 200px;
table {
    border-collapse: collapse;
    tbody {
        tr {
            td {
                padding: .5em .75em;
                box-shadow: inset 0px -1px 0px 0px #000000;
                position: relative;
                z-index: -9999;
                background: white;
                &:first-of-type {
                    position: -webkit-sticky;
                    position: sticky;
                    left: 0px;
                    background: #eee;
                    z-index: -999;
                    box-shadow: inset -1px -1px 0px 0px #000000;
                }
            }
            &:first-of-type {
                position: sticky;
                top: 0;
                td {
                    background: #eee; 
                    &:first-of-type {
                        left: 0;
                        top: 0;
                        background: #eee;
                        z-index: 999;
                    }
                }
            }
            &:nth-of-type(2) {
                position: sticky;
                top: calc(1em + 1em + 2px);
                background: white;
                td:first-of-type {
                    position: sticky;
                    left: 0;
                    z-index: 998;
                }
            }
        }
    }
}

}

https://codepen.io/the_Northway/pen/VwMmwXG


1

经过两天与Internet Explorer 9 + Chrome + Firefox(Windows)和Safari(Mac)的斗争,我找到了一个系统,它是:

  • 与所有这些浏览器兼容
  • 不使用JavaScript
  • 仅使用一个div和一个table
  • 固定的页眉和页脚(除IE外),具有可滚动的正文。页眉和正文具有相同的列宽度

结果: enter image description here

HTML:

  <thead>
    <tr>
      <th class="nombre"><%= f.label :cost_center %></th>
      <th class="cabecera cc">Personal</th>
      <th class="cabecera cc">Dpto</th>
    </tr>
  </thead>
  <tbody>
    <% @cost_centers.each do |cc| %>
    <tr>
      <td class="nombre"><%= cc.nombre_corto %></td>
      <td class="cc"><%= cc.cacentrocoste %></td>
      <td class="cc"><%= cc.cacentrocoste_dpto %></td>
    </tr>
    <% end %>
  </tbody>
  <tfoot>
    <tr>
      <td colspan="3"><a href="#">Mostrar mas usuarios</a></td>
    </tr>
  </tfoot>
</table>

CSS:
div.cost_center{
  width:320px;
  font-size:75%;
  margin-left:5px;
  margin-top:5px;
  margin-bottom: 2px;
  float: right;
  display: inline-block;
  overflow-y: auto;
  overflow-x: hidden;
  max-height:300px;  
}

div.cost_center label { 
  float:none;
  font-size:14px;
}

div.cost_center table{
  width:300px;
  border-collapse: collapse; 
  float:right;
  table-layout:fixed;
}

div.cost_center table tr{
  height:16px;
}
div.cost_center th{
  font-weight:normal;
}

div.cost_center table tbody{
  display: block;
  overflow: auto;
  max-height:240px;
}

div.cost_center table thead{
  display:block;
}

div.cost_center table tfoot{
  display:block;
}
div.cost_center table tfoot td{
  width:280px;
}
div.cost_center .cc{
  width:60px;
  text-align: center; 
  border: 1px solid #999;
}

div.cost_center .nombre{
  width:150px;
}
div.cost_center tbody .nombre{
  border: 1px solid #999;
}

div.cost_center table tfoot td{
 text-align:center;  
 border: 1px solid #999; 
} 

div.cost_center table th, 
div.cost_center table td { 
  padding: 2px;
  vertical-align: middle; 
}

div.cost_center table tbody td {
  white-space: normal;
  font:  .8em/1.4em Verdana, sans-serif;
  color: #000;
  background-color: white;
}
div.cost_center table th.cabecera { 
  font:  0.8em/1.4em Verdana, sans-serif;
  color: #000;
  background-color: #FFEAB5;
}

不错的尝试,但对我来说效果不太好。在这个例子(http://jsfiddle.net/5ka6e/)中,标题没有正确地调整大小。这种错误最终可能会导致数据和标题不匹配。 - darkzangel
1
你忘记添加 div.cost_center table{border-collapse: collapse;},第三个标题必须适合60px(在此示例中)。 - Albert Català

1

/* Use overflow:scroll on your container to enable scrolling: */

div {
  max-width: 400px;
  max-height: 150px;
  overflow: scroll;
}


/* Use position: sticky to have it stick to the edge
 * and top, right, or left to choose which edge to stick to: */

thead th {
  position: -webkit-sticky; /* for Safari */
  position: sticky;
  top: 0;
}

tbody th {
  position: -webkit-sticky; /* for Safari */
  position: sticky;
  left: 0;
}


/* To have the header in the first column stick to the left: */

thead th:first-child {
  left: 0;
  z-index: 1;
}


/* Just to display it nicely: */

thead th {
  background: #000;
  color: #FFF;
}

tbody th {
  background: #FFF;
  border-right: 1px solid #CCC;
}

table {
  border-collapse: collapse;
}

td,
th {
  padding: 0.5em;
}
<div>
  <table>
    <thead>
      <tr>
        <th></th>
        <th>headheadhead</th>
        <th>headheadhead</th>
        <th>headheadhead</th>
        <th>headheadhead</th>
        <th>headheadhead</th>
        <th>headheadhead</th>
        <th>headheadhead</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th>head</th>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
      </tr>
      <tr>
        <th>head</th>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
      </tr>
      <tr>
        <th>head</th>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
      </tr>
      <tr>
        <th>head</th>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
      </tr>
      <tr>
        <th>head</th>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
      </tr>
      <tr>
        <th>head</th>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
        <td>body</td>
      </tr>
    </tbody>
  </table>
</div>

需要修复页眉和页脚。

1

我和一位同事刚刚发布了一个新的GitHub项目,提供了一个Angular指令,您可以使用它来装饰您的表格并固定表头: https://github.com/objectcomputing/FixedHeader

它仅依赖于css和angular,使用一个指令添加一些div。不需要jQuery。

这个实现可能没有其他实现那么全面,但是如果您只需要添加固定表格,我们认为这可能是一个不错的选择。


0

你可以尝试类似这样的方法... 可能需要为标题行设置列宽。

thead { 
    position: fixed;
}

http://jsfiddle.net/vkhNC/

更新:

我不确定你提供的示例是否仅使用CSS就可以实现。我希望有人能证明我是错的。这是我目前为止的成果。虽然它还不是最终产品,但可能对你有所启发。我希望这能指引你朝着有用的方向前进。


我需要的不仅仅是表头,而且第一列也需要固定。 - panfil
5
问题是表头失去了它们的宽度。由于表头列的大小和数据列的大小不同,这看起来很丑。 - Akash Kava

0

纯CSS实例:

<div id="cntnr">
    <div class="tableHeader">
        <table class="table-header table table-striped table-bordered">
            <thead>
                <tr>
                    <th>this</th>
                    <th>transmission</th>
                    <th>is</th>
                    <th>coming</th>
                    <th>to</th>
                    <th>you</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>we've got it...</td>
                    <td>alright you are go</td>
                    <td>uh, we see the Earth now</td>
                    <td>we've got it...</td>
                    <td>alright you are go</td>
                    <td>uh, we see the Earth now</td>
                </tr>
            </tbody>
        </table>
    </div>


    <div class="tableBody">
        <table class="table-body table table-striped table-bordered">
            <thead>
                <tr>
                    <th>this</th>
                    <th>transmission</th>
                    <th>is</th>
                    <th>coming</th>
                    <th>to</th>
                    <th>you</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>we've got it...</td>
                    <td>alright you are go</td>
                    <td>uh, we see the Earth now</td>
                    <td>we've got it...</td>
                    <td>alright you are go</td>
                    <td>uh, we see the Earth now</td>
                </tr>
            </tbody>
        </table>
    </div>

</div>

#cntnr {
    width: auto;
    height: 200px;
    border: solid 1px #444;
    overflow: auto;
}

.tableHeader {
    position: fixed;
    height: 40px;
    overflow: hidden;
    margin-right: 18px;
    background: white;
}

.table-header tbody {
    height: 0;
    visibility: hidden;
}

.table-body thead {
    height: 0;
    visibility: hidden;
}

http://jsfiddle.net/cCarlson/L98m854d/

缺点:固定的标题结构/逻辑相当依赖于特定的尺寸,因此抽象化可能不是可行的选择


需要固定表头和第一列。 - panfil
啊...谢谢你指出来,panfil。我会进行编辑。谢谢。 - Cody

0

0

0

定位:sticky 在 Chrome 和其他 Webkit 浏览器(如 Safari)中对某些元素(如 thead)无效。

但是它与 th 元素一起使用时效果很好。

body {
  background-color: rgba(0, 255, 200, 0.1);
}

.intro {
  color: rgb(228, 23, 23);
}

.wrapper {
  overflow-y: scroll;
  height: 300px;
}

.sticky {
  position: sticky;
  top: 0;
  color: black;
  background-color: white;
}
<div class="container intro">
  <h1>Sticky Table Header</h1>
  <p>Postion : sticky doesn't work for some elements like (thead) in chrome and other webkit browsers like safari. </p>
  <p>But it works fine with (th)</p>
</div>
<div class="container wrapper">
  <table class="table table-striped">
    <thead>
      <tr>
        <th class="sticky">Firstname</th>
        <th class="sticky">Lastname</th>
        <th class="sticky">Email</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>James</td>
        <td>Vince</td>
        <td>james@example.com</td>
      </tr>
      <tr>
        <td>Jonny</td>
        <td>Bairstow</td>
        <td>jonny@example.com</td>
      </tr>
      <tr>
        <td>James</td>
        <td>Anderson</td>
        <td>james@example.com</td>
      </tr>
      <tr>
        <td>Stuart</td>
        <td>Broad</td>
        <td>stuart@example.com</td>
      </tr>
      <tr>
        <td>Eoin</td>
        <td>Morgan</td>
        <td>eoin@example.com</td>
      </tr>
      <tr>
        <td>Joe</td>
        <td>Root</td>
        <td>joe@example.com</td>
      </tr>
      <tr>
        <td>Chris</td>
        <td>Woakes</td>
        <td>chris@example.com</td>
      </tr>
      <tr>
        <td>Liam</td>
        <td>PLunkett</td>
        <td>liam@example.com</td>
      </tr>
      <tr>
        <td>Jason</td>
        <td>Roy</td>
        <td>jason@example.com</td>
      </tr>
      <tr>
        <td>Alex</td>
        <td>Hales</td>
        <td>alex@example.com</td>
      </tr>
      <tr>
        <td>Jos</td>
        <td>Buttler</td>
        <td>jos@example.com</td>
      </tr>
      <tr>
        <td>Ben</td>
        <td>Stokes</td>
        <td>ben@example.com</td>
      </tr>
      <tr>
        <td>Jofra</td>
        <td>Archer</td>
        <td>jofra@example.com</td>
      </tr>
      <tr>
        <td>Mitchell</td>
        <td>Starc</td>
        <td>mitchell@example.com</td>
      </tr>
      <tr>
        <td>Aaron</td>
        <td>Finch</td>
        <td>aaron@example.com</td>
      </tr>
      <tr>
        <td>David</td>
        <td>Warner</td>
        <td>david@example.com</td>
      </tr>
      <tr>
        <td>Steve</td>
        <td>Smith</td>
        <td>steve@example.com</td>
      </tr>
      <tr>
        <td>Glenn</td>
        <td>Maxwell</td>
        <td>glenn@example.com</td>
      </tr>
      <tr>
        <td>Marcus</td>
        <td>Stoinis</td>
        <td>marcus@example.com</td>
      </tr>
      <tr>
        <td>Alex</td>
        <td>Carey</td>
        <td>alex@example.com</td>
      </tr>
      <tr>
        <td>Nathan</td>
        <td>Coulter Nile</td>
        <td>nathan@example.com</td>
      </tr>
      <tr>
        <td>Pat</td>
        <td>Cummins</td>
        <td>pat@example.com</td>
      </tr>
      <tr>
        <td>Adam</td>
        <td>Zampa</td>
        <td>zampa@example.com</td>
      </tr>
    </tbody>
  </table>
</div>

或者 访问我的 CodePen 示例

-1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接