宽度为100%的HTML表格,在tbody中有垂直滚动

Mar*_*o S 387 html css css3 vertical-scrolling

如何设置<table>100%宽度并仅在<tbody>垂直滚动内放置一些高度?

tbody里面的垂直滚动

table {
    width: 100%;
    display:block;
}
thead {
    display: inline-block;
    width: 100%;
    height: 20px;
}
tbody {
    height: 200px;
    display: inline-block;
    width: 100%;
    overflow: auto;
}
  
Run Code Online (Sandbox Code Playgroud)
<table>
  <thead>
    <tr>
    	<th>Head 1</th>
    	<th>Head 2</th>
    	<th>Head 3</th>
    	<th>Head 4</th>
    	<th>Head 5</th>
    </tr>
  </thead>
  <tbody>
    <tr>
    	<td>Content 1</td>
    	<td>Content 2</td>
    	<td>Content 3</td>
    	<td>Content 4</td>
    	<td>Content 5</td>
    </tr>
  </tbody>
</table>
Run Code Online (Sandbox Code Playgroud)

我希望避免增加一些额外的div,我要的是简单的表像这样,当我试图改变显示table-layout,position在CSS表以及更多的东西没有工作好与100%的宽度仅与PX固定宽度.

Has*_*ami 629

为了使<tbody>元素可滚动,我们需要改变它在页面上显示的方式,即使用display: block;将其显示为块级元素.

由于我们更改了display属性tbody,我们应该更改thead元素的属性以防止破坏表格布局.

所以我们有:

thead, tbody { display: block; }

tbody {
    height: 100px;       /* Just for the demo          */
    overflow-y: auto;    /* Trigger vertical scroll    */
    overflow-x: hidden;  /* Hide the horizontal scroll */
}
Run Code Online (Sandbox Code Playgroud)

Web浏览器默认将theadtbody元素显示为行组(table-header-grouptable-row-group).

一旦我们更改了它,内部tr元素就不会填充其容器的整个空间.

为了解决这个问题,我们必须计算tbody列的宽度,并thead通过JavaScript 将相应的值应用于列.

自动宽度列

这是上面逻辑的jQuery版本:

// Change the selector if needed
var $table = $('table'),
    $bodyCells = $table.find('tbody tr:first').children(),
    colWidth;

// Get the tbody columns width array
colWidth = $bodyCells.map(function() {
    return $(this).width();
}).get();

// Set the width of thead columns
$table.find('thead tr').children().each(function(i, v) {
    $(v).width(colWidth[i]);
});    
Run Code Online (Sandbox Code Playgroud)

这是输出(在Windows 7 Chrome 32上):

tbody里面的垂直滚动

工作演示.

全宽表,相对宽度列

正如原始海报所需,我们可以扩展tablewidth其容器的100%,然后使用表的每列的相对(百分比)width.

table {
    width: 100%; /* Optional */
}

tbody td, thead th {
    width: 20%;  /* Optional */
}
Run Code Online (Sandbox Code Playgroud)

由于表具有(某种)流体布局,我们应该thead在容器调整大小时调整列的宽度.

因此,一旦调整窗口大小,我们应该设置列的宽度:

// Adjust the width of thead cells when *window* resizes
$(window).resize(function() {
    /* Same as before */ 
}).resize(); // Trigger the resize handler once the script runs
Run Code Online (Sandbox Code Playgroud)

输出将是:

流体表与tbody内的垂直滚动

工作演示.


浏览器支持和替代方案

我已经通过新版本的主要Web浏览器(包括IE10 +)在Windows 7上测试了上述两种方法,并且它有效.

但是,它 工作 正常 上IE9及以下.

那是因为表格布局中,所有元素都应遵循相同的结构属性.

通过使用display: block;<thead><tbody>元素,我们把这个表结构.

通过JavaScript重新设计布局

一种方法是重新设计(整个)表格布局.使用JavaScript动态创建新布局并动态处理和/或调整单元格的宽度/高度.

例如,看看以下示例:

嵌套表

此方法使用两个嵌套表,其中包含div.第一个table只有一个具有a的单元格,div第二个表格放在该div元素内部.

检查垂直滚动表CSS播放.

这适用于大多数Web浏览器.我们也可以通过JavaScript动态地完成上述逻辑.

滚动固定标题表

由于添加垂直滚动条的目的<tbody>是在每行的顶部显示表,我们可以将元素定位在屏幕的顶部.theadfixed

这是Julien执行的这种方法的工作演示. 它有一个很有前途的Web浏览器支持.

而且在这里一个纯CSS通过实施威廉·Bockstal.


纯CSS解决方案

这是旧答案.当然我添加了一个新方法并改进了CSS声明.

固定宽度的表

在这种情况下,table应该有一个固定的width (包括列的宽度和垂直滚动条的宽度).

应具有特定的宽度最后一列thead元素需要更大的宽度,其等于该他人的宽度 +的宽度垂直滚动条的.

因此,CSS将是:

table {
    width: 716px; /* 140px * 5 column + 16px scrollbar width */
    border-spacing: 0;
}

tbody, thead tr { display: block; }

tbody {
    height: 100px;
    overflow-y: auto;
    overflow-x: hidden;
}

tbody td, thead th {
    width: 140px;
}

thead th:last-child {
    width: 156px; /* 140px + 16px scrollbar width */
}
Run Code Online (Sandbox Code Playgroud)

这是输出:

固定宽度的表

工作演示.

表100%宽度

在这种方法中,table宽度为100%和每个,th并且属性tdwidth应小于100% / number of cols.

此外,我们需要降低宽度thead作为的值宽度垂直滚动条的.

为了做到这一点,我们需要使用CSS3 calc()函数,如下所示:

table {
    width: 100%;
    border-spacing: 0;
}

thead, tbody, tr, th, td { display: block; }

thead tr {
    /* fallback */
    width: 97%;
    /* minus scroll bar width */
    width: -webkit-calc(100% - 16px);
    width:    -moz-calc(100% - 16px);
    width:         calc(100% - 16px);
}

tr:after {  /* clearing float */
    content: ' ';
    display: block;
    visibility: hidden;
    clear: both;
}

tbody {
    height: 100px;
    overflow-y: auto;
    overflow-x: hidden;
}

tbody td, thead th {
    width: 19%;  /* 19% is less than (100% / 5 cols) = 20% */
    float: left;
}
Run Code Online (Sandbox Code Playgroud)

这是在线演示.

注意:如果每列的内容打破了这一行,这种方法将失败,即每个单元格的内容应足够短.


在下面,有两个简单的纯CSS解决方案示例,我在回答这个问题时创建了它.

这是jsFiddle演示版v2.

旧版本:jsFiddle演示版 v1

  • 使用`display:block`,您可以将表的属性作为列在thead和tbody之间共享的宽度.我知道你已经通过设置`width:19.2%`来解决这个问题,但是如果我们事先不知道每列的宽度,这将不起作用. (15认同)
  • 这段代码似乎假设身体单元格总是比标题单元格宽. (9认同)
  • 当“高度:100%”(当您希望表格扩展到页面底部时)不起作用。 (2认同)
  • 这也可以与AngularJS`ng-repeat`表一起使用。不确定为什么所有这些库都具有固定的表头,如果有此解决方案,为什么不行。 (2认同)
  • 您可以使用`box-sizing`属性来进一步改善此功能,以使具有两个不同厚度的边框不会影响列对齐。 (2认同)

tsa*_*yen 84

在以下解决方案中,表占用父容器的100%,不需要绝对大小.它是纯CSS,使用flex布局.

以下是它的外观: 在此输入图像描述

可能的缺点:

  • 无论是否需要,垂直滚动条始终可见;
  • 表格布局是固定的 - 列不会根据内容宽度调整大小(您仍然可以设置您想要的任何列宽度);
  • 有一个绝对大小 - 滚动条的宽度,对于我能够检查的浏览器大约是0.9em.

HTML(缩写):

<div class="table-container">
    <table>
        <thead>
            <tr>
                <th>head1</th>
                <th>head2</th>
                <th>head3</th>
                <th>head4</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>content1</td>
                <td>content2</td>
                <td>content3</td>
                <td>content4</td>
            </tr>
            <tr>
                <td>content1</td>
                <td>content2</td>
                <td>content3</td>
                <td>content4</td>
            </tr>
            ...
        </tbody>
    </table>
</div>
Run Code Online (Sandbox Code Playgroud)

CSS,为清晰起见省略了一些装饰:

.table-container {
    height: 10em;
}
table {
    display: flex;
    flex-flow: column;
    height: 100%;
    width: 100%;
}
table thead {
    /* head takes the height it requires, 
    and it's not scaled when table is resized */
    flex: 0 0 auto;
    width: calc(100% - 0.9em);
}
table tbody {
    /* body takes all the remaining available space */
    flex: 1 1 auto;
    display: block;
    overflow-y: scroll;
}
table tbody tr {
    width: 100%;
}
table thead, table tbody tr {
    display: table;
    table-layout: fixed;
}
Run Code Online (Sandbox Code Playgroud)

关于jsfiddle的完整代码

LESS中的代码相同,因此您可以将其混合使用:

.table-scrollable() {
  @scrollbar-width: 0.9em;
  display: flex;
  flex-flow: column;

  thead,
  tbody tr {
    display: table;
    table-layout: fixed;
  }

  thead {
    flex: 0 0 auto;
    width: ~"calc(100% - @{scrollbar-width})";
  }

  tbody {
    display: block;
    flex: 1 1 auto;
    overflow-y: scroll;

    tr {
      width: 100%;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 感谢您的解决方案!有一个小错误。。。您为thead设置了两次宽度,我发现从宽度中减去1.05em会更好一些:https://jsfiddle.net/xuvsncr2/170/ (2认同)
  • @tsayen 在调整窗口大小时如何阻止它卷起和重叠? (2认同)

Gau*_*uss 26

在现代浏览器中,您可以简单地使用css:

th {
  position: sticky;
  top: 0;
  z-index: 2;
}
Run Code Online (Sandbox Code Playgroud)

  • 这个咒语是不完整的......关心发表一个例子,或者至少详细说明? (5认同)
  • 当您用具有“overflow-y: auto;”和一些“max-height”的“&lt;div&gt;”包装“&lt;table&gt;”时,此答案有效。例如:`&lt;div style="overflow-y: auto; max-height: 400px;"&gt;&lt;table&gt;...&lt;/table&gt;&lt;/div&gt;` (3认同)
  • 最简单的解决方案!不过,正如 @Minwork 提到的,您必须将表格放在 div 标签内,并为其指定最大高度才能看到效果。 (2认同)

gav*_*che 18

我使用display:blocktheadtbody.因此,thead列的宽度不同于列的宽度tbody.

table {
    margin:0 auto; 
    border-collapse:collapse;
}
thead {
    background:#CCCCCC;
    display:block
}
tbody {
    height:10em;overflow-y:scroll;
    display:block
}
Run Code Online (Sandbox Code Playgroud)

为了解决这个问题,我使用的是小jQuery代码,但它只能用于完成JavaScript.

var colNumber=3 //number of table columns    

for (var i=0; i<colNumber; i++) {
  var thWidth=$("#myTable").find("th:eq("+i+")").width();
  var tdWidth=$("#myTable").find("td:eq("+i+")").width();      
  if (thWidth<tdWidth)                    
      $("#myTable").find("th:eq("+i+")").width(tdWidth);
  else
      $("#myTable").find("td:eq("+i+")").width(thWidth);           
}  
Run Code Online (Sandbox Code Playgroud)

这是我的工作演示:http: //jsfiddle.net/gavroche/N7LEF/

在IE 8中不起作用

var colNumber=3 //number of table columns


for (var i=0; i<colNumber; i++)
  {
      var thWidth=$("#myTable").find("th:eq("+i+")").width();
      var tdWidth=$("#myTable").find("td:eq("+i+")").width();      
      if (thWidth<tdWidth)                    
          $("#myTable").find("th:eq("+i+")").width(tdWidth);
      else
          $("#myTable").find("td:eq("+i+")").width(thWidth);           
  }  
Run Code Online (Sandbox Code Playgroud)
 table {margin:0 auto; border-collapse:separate;}
 thead {background:#CCCCCC;display:block}
 tbody {height:10em;overflow-y:scroll;display:block}
Run Code Online (Sandbox Code Playgroud)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<table id="myTable" border="1">
    <thead>
        <tr>
            <th>A really Very Long Header Text</th>
            <th>Normal Header</th>
            <th>Short</th>            
        </tr>    
    </thead>
    <tbody>
        <tr>
            <td>
                Text shorter than header
            </td>
            <td>
                Text is longer than header
            </td>
            <td>
                Exact
            </td>
        </tr>
        <tr>
            <td>
                Text shorter than header
            </td>
            <td>
                Text is longer than header
            </td>
            <td>
                Exact
            </td>
        </tr>
        <tr>
            <td>
                Text shorter than header
            </td>
            <td>
                Text is longer than header
            </td>
            <td>
                Exact
            </td>
        </tr>
        <tr>
            <td>
                Text shorter than header
            </td>
            <td>
                Text is longer than header
            </td>
            <td>
                Exact
            </td>
        </tr>
        <tr>
            <td>
                Text shorter than header
            </td>
            <td>
                Text is longer than header
            </td>
            <td>
                Exact
            </td>
        </tr>
        <tr>
            <td>
                Text shorter than header
            </td>
            <td>
                Text is longer than header
            </td>
            <td>
                Exact
            </td>
        </tr>
        <tr>
            <td>
                Text shorter than header
            </td>
            <td>
                Text is longer than header
            </td>
            <td>
                Exact
            </td>
        </tr>
        <tr>
            <td>
                Text shorter than header
            </td>
            <td>
                Text is longer than header
            </td>
            <td>
                Exact
            </td>
        </tr>
        <tr>
            <td>
                Text shorter than header
            </td>
            <td>
                Text is longer than header
            </td>
            <td>
                Exact
            </td>
        </tr>
        <tr>
            <td>
                Text shorter than header
            </td>
            <td>
                Text is longer than header
            </td>
            <td>
                Exact
            </td>
        </tr>
        <tr>
            <td>
                Text shorter than header
            </td>
            <td>
                Text is longer than header
            </td>
            <td>
                Exact
            </td>
        </tr>
    </tbody>
</table>
Run Code Online (Sandbox Code Playgroud)


Sus*_*mar 14

依次创建两个表,将第二个表放在固定高度的div中,并将overflow属性设置为auto.同时将第二个表中的所有td保留在第二个表中.

<div>
    <table>
        <thead>
            <tr>
                <th>Head 1</th>
                <th>Head 2</th>
                <th>Head 3</th>
                <th>Head 4</th>
                <th>Head 5</th>
            </tr>
        </thead>
    </table>
</div>

<div style="max-height:500px;overflow:auto;">
    <table>
        <thead>
            <tr>
                <th></th>
                <th></th>
                <th></th>
                <th></th>
                <th></th>
            </tr>
        </thead>
        <tbody>
        <tr>
            <td>Content 1</td>
            <td>Content 2</td>
            <td>Content 3</td>
            <td>Content 4</td>
            <td>Content 5</td>
        </tr>
        </tbody>
    </table>    
</div>
Run Code Online (Sandbox Code Playgroud)

  • 在这种情况下,第二个表列不能跟随第一个表的宽度. (8认同)
  • 最理智的方法!<3 (4认同)
  • 不好!您将丢失两个表上的列的宽度同步。 (2认同)

Rok*_*jan 10

仅CSS

适用于Chrome,Firefox,Edge(和其他常绿浏览器)

只是position: sticky; top: 0;您的th元素:

/* Fix table head */
.tableFixHead    { overflow-y: auto; height: 100px; }
.tableFixHead th { position: sticky; top: 0; }

/* Just common table stuff. */
table  { border-collapse: collapse; width: 100%; }
th, td { padding: 8px 16px; }
th     { background:#eee; }
Run Code Online (Sandbox Code Playgroud)
<div class="tableFixHead">
  <table>
    <thead>
      <tr><th>TH 1</th><th>TH 2</th></tr>
    </thead>
    <tbody>
      <tr><td>A1</td><td>A2</td></tr>
      <tr><td>B1</td><td>B2</td></tr>
      <tr><td>C1</td><td>C2</td></tr>
      <tr><td>D1</td><td>D2</td></tr>
      <tr><td>E1</td><td>E2</td></tr>
    </tbody>
  </table>
</div>
Run Code Online (Sandbox Code Playgroud)

PS:如果需要TH元素的边框th {box-shadow: 1px 1px 0 #000; border-top: 0;}则将有所帮助(因为默认边框在滚动时未正确绘制)。

对于上述仅使用少量JS来适应IE11的变体,请参见以下答案/sf/answers/3354653571/

  • 这实际上是解决问题的最佳方案。但我认为最好使整个标题行粘起来(即.tableFixHead thead tr)而不是第 th 元素,然后您还可以“粘住”标题行的样式。 (2认同)

Mik*_*stö 6

按照以下说明,我最终使用纯CSS得到了它:

http://tjvantoll.com/2012/11/10/creating-cross-browser-scrollable-tbody/

第一步是设置<tbody>显示:块,以便可以应用溢出和高度.从那里<thead>需要将行设置为position:relative和display:block,以便它们位于现在可滚动的顶部<tbody>.

tbody, thead { display: block; overflow-y: auto; }

因为<thead>相对定位,每个表格单元格需要明确的宽度

td:nth-child(1), th:nth-child(1) { width: 100px; }
td:nth-child(2), th:nth-child(2) { width: 100px; }
td:nth-child(3), th:nth-child(3) { width: 100px; }
Run Code Online (Sandbox Code Playgroud)

但不幸的是,这还不够.当存在滚动条时,浏览器为它分配空间,因此,<tbody>最终可用空间比可用空间少<thead>.注意这会造成轻微的错位......

我能想到的唯一解决方法是在除最后一列之外的所有列上设置最小宽度.

td:nth-child(1), th:nth-child(1) { min-width: 100px; }
td:nth-child(2), th:nth-child(2) { min-width: 100px; }
td:nth-child(3), th:nth-child(3) { width: 100px; }
Run Code Online (Sandbox Code Playgroud)

整个codepen示例如下:

CSS:

.fixed_headers {
  width: 750px;
  table-layout: fixed;
  border-collapse: collapse;
}
.fixed_headers th {
  text-decoration: underline;
}
.fixed_headers th,
.fixed_headers td {
  padding: 5px;
  text-align: left;
}
.fixed_headers td:nth-child(1),
.fixed_headers th:nth-child(1) {
  min-width: 200px;
}
.fixed_headers td:nth-child(2),
.fixed_headers th:nth-child(2) {
  min-width: 200px;
}
.fixed_headers td:nth-child(3),
.fixed_headers th:nth-child(3) {
  width: 350px;
}
.fixed_headers thead {
  background-color: #333333;
  color: #fdfdfd;
}
.fixed_headers thead tr {
  display: block;
  position: relative;
}
.fixed_headers tbody {
  display: block;
  overflow: auto;
  width: 100%;
  height: 300px;
}
.fixed_headers tbody tr:nth-child(even) {
  background-color: #dddddd;
}
.old_ie_wrapper {
  height: 300px;
  width: 750px;
  overflow-x: hidden;
  overflow-y: auto;
}
.old_ie_wrapper tbody {
  height: auto;
}
Run Code Online (Sandbox Code Playgroud)

HTML:

<!-- IE < 10 does not like giving a tbody a height.  The workaround here applies the scrolling to a wrapped <div>. -->
<!--[if lte IE 9]>
<div class="old_ie_wrapper">
<!--<![endif]-->

<table class="fixed_headers">
  <thead>
    <tr>
      <th>Name</th>
      <th>Color</th>
      <th>Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Apple</td>
      <td>Red</td>
      <td>These are red.</td>
    </tr>
    <tr>
      <td>Pear</td>
      <td>Green</td>
      <td>These are green.</td>
    </tr>
    <tr>
      <td>Grape</td>
      <td>Purple / Green</td>
      <td>These are purple and green.</td>
    </tr>
    <tr>
      <td>Orange</td>
      <td>Orange</td>
      <td>These are orange.</td>
    </tr>
    <tr>
      <td>Banana</td>
      <td>Yellow</td>
      <td>These are yellow.</td>
    </tr>
    <tr>
      <td>Kiwi</td>
      <td>Green</td>
      <td>These are green.</td>
    </tr>
    <tr>
      <td>Plum</td>
      <td>Purple</td>
      <td>These are Purple</td>
    </tr>
    <tr>
      <td>Watermelon</td>
      <td>Red</td>
      <td>These are red.</td>
    </tr>
    <tr>
      <td>Tomato</td>
      <td>Red</td>
      <td>These are red.</td>
    </tr>
    <tr>
      <td>Cherry</td>
      <td>Red</td>
      <td>These are red.</td>
    </tr>
    <tr>
      <td>Cantelope</td>
      <td>Orange</td>
      <td>These are orange inside.</td>
    </tr>
    <tr>
      <td>Honeydew</td>
      <td>Green</td>
      <td>These are green inside.</td>
    </tr>
    <tr>
      <td>Papaya</td>
      <td>Green</td>
      <td>These are green.</td>
    </tr>
    <tr>
      <td>Raspberry</td>
      <td>Red</td>
      <td>These are red.</td>
    </tr>
    <tr>
      <td>Blueberry</td>
      <td>Blue</td>
      <td>These are blue.</td>
    </tr>
    <tr>
      <td>Mango</td>
      <td>Orange</td>
      <td>These are orange.</td>
    </tr>
    <tr>
      <td>Passion Fruit</td>
      <td>Green</td>
      <td>These are green.</td>
    </tr>
  </tbody>
</table>

<!--[if lte IE 9]>
</div>
<!--<![endif]-->
Run Code Online (Sandbox Code Playgroud)

编辑:表宽100%的替代解决方案(实际上是固定宽度,并没有回答问题):

HTML:

<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Color</th>
      <th>Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Apple</td>
      <td>Red</td>
      <td>These are red.</td>
    </tr>
    <tr>
      <td>Pear</td>
      <td>Green</td>
      <td>These are green.</td>
    </tr>
    <tr>
      <td>Grape</td>
      <td>Purple / Green</td>
      <td>These are purple and green.</td>
    </tr>
    <tr>
      <td>Orange</td>
      <td>Orange</td>
      <td>These are orange.</td>
    </tr>
    <tr>
      <td>Banana</td>
      <td>Yellow</td>
      <td>These are yellow.</td>
    </tr>
    <tr>
      <td>Kiwi</td>
      <td>Green</td>
      <td>These are green.</td>
    </tr>
  </tbody>
</table>
Run Code Online (Sandbox Code Playgroud)

CSS:

table {
  width: 100%;
  text-align: left;
  min-width: 610px;
}
tr {
  height: 30px;
  padding-top: 10px
}
tbody { 
  height: 150px; 
  overflow-y: auto;
  overflow-x: hidden;
}
th,td,tr,thead,tbody { display: block; }
td,th { float: left; }
td:nth-child(1),
th:nth-child(1) {
  width: 20%;
}
td:nth-child(2),
th:nth-child(2) {
  width: 20%;
  float: left;
}
td:nth-child(3),
th:nth-child(3) {
  width: 59%;
  float: left;
}
/* some colors */
thead {
  background-color: #333333;
  color: #fdfdfd;
}
table tbody tr:nth-child(even) {
  background-color: #dddddd;
}
Run Code Online (Sandbox Code Playgroud)

演示:http://codepen.io/anon/pen/bNJeLO