宽度为100%的HTML表格,tbody内部有垂直滚动条

我怎样才能设置<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;
}
  
<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>

为了使<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 */
}

Web浏览器tbodytheadtbody元素显示为行组( table-header-grouptable-row-group )。

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

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

自动宽度列

这是以上逻辑的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]);
});    

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

tbody内的垂直滚动

工作演示

全宽表,相对宽度列

由于需要使用原始海报,我们可以将table展开至其容器width的100%,然后对表格的每一列使用相对(百分比) width

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

tbody td, thead th {
    width: 20%;  /* Optional */
}

由于表中有一个(排序的) 流体布局 ,要调整的宽度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

输出将是:

流体表与tbody内的垂直滚动

工作演示


浏览器支持和替代品

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

但是,它在IE9及以下版本中无法正常工作。

这是因为在表格布局中,所有元素应该遵循相同的结构特性。

通过使用display: block; 对于<thead><tbody>元素,我们打破了表结构。

通过JavaScript重新设计布局

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

例如,看看下面的例子:

  • jQuery .floatThead()插件(浮动/锁定/粘贴表头插件)
  • jQuery可滚动表格插件。 (源代码在github上)
  • jQuery .FixedHeaderTable()插件(github上的源代码)
  • DataTables 垂直滚动的例子。
  • 嵌套表

    这种方法使用两个嵌套的表格和一个包含div的表格。 第一个table只有一个具有div单元格,第二个表格放置在该div元素内。

    在CSS Play上检查垂直滚动表。

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

    滚动上带有固定标题的表格

    由于添加垂直滚动条到的目的<tbody>被显示在每一行的顶部表 ,我们可以在定位 thead元件留fixed在屏幕代替的顶部。

    这是朱利安执行的这种方法的工作演示
    它具有很好的网页浏览器支持。

    这里是Willem Van Bockstal的纯CSS实现。


    纯粹的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 */
    }
    

    这是输出:

    固定宽度的表

    工作演示

    100%宽度的桌子

    在这种方法中, table的宽度为100% ,对于每个thtdwidth属性的值应小于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;
    }
    

    这里是在线演示

    注意:如果每列的内容打破了这条线,那么这种方法就会失败 ,即每个单元的内容应该足够短


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

    这是jsFiddle Demo v2

    旧版本: jsFiddle Demo v1


    在以下解决方案中,表占用父容器的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>
    

    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;
    }
    

    完整的代码在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%;
        }
      }
    }
    

    我为theadtbody使用display:block 。 因认为的宽度thead列是从宽度不同tbody列。

    table {margin:0 auto; border-collapse:collapse;} thead {background:#CCCCCC;display:block} tbody {height:10em;overflow-y:scroll;display:block}

    为了解决这个问题,我使用小型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);           
      }  
    

    这是我的工作演示: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);           
      }  
     table {margin:0 auto; border-collapse:separate;}
     thead {background:#CCCCCC;display:block}
     tbody {height:10em;overflow-y:scroll;display:block}
    <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>
    链接地址: http://www.djcxy.com/p/15505.html

    上一篇: HTML table with 100% width, with vertical scroll inside tbody

    下一篇: Div height 100% and expands to fit content