概述

table 用来定义表格,一个简单的 table 元素一般由一个或多个 tr、th 或 td 元素组成,其中 tr 元素定义表格行,th 元素定义表头,td 元素定义表格单元。而一个复杂的 table 可能包括 caption、col、colgroup、thead、tfoot 以及 tbody 元素。

简单的 table 演示这里就不做过多介绍了,这里主要介绍一些 table 使用技巧。

布局算法

表格布局算法也是一件比较纠结的事,其属性为 table-layout,取值有:

  • auto:自动布局,列的宽度是由列单元格中没有折行的最宽的内容设定的
  • fixed:固定布局,列的宽度取决于表格宽度、列宽度、表格边框宽度、单元格间距,而与单元格的内容无关,与自动布局相比,浏览器可以更快得对表格进行布局。

默认如果不设置table 及列的宽度,不论使用什么布局,table的宽度及列的宽度都由内容撑开。

而如果对 table 设置一个宽度,如“100%”,则列宽度存在以下几种情况:

  • 没有任何列设置宽度,则列的宽度由其内容按比例分配
  • 如果有某一列或几列设置了宽度,则剩余的由其内容按比例分配
  • 如果每列都设置了宽度,每列的宽度加起来不等于table的宽度,则按照列设置的宽度比例重新分配宽度,而不是实际列设置的宽度

如果在设置 table 宽度的前提下,再设置其为固定布局,则列宽度存在以下几种情况:

  • 没有任何列设置宽度,则宽度等分
  • 如果有某一列或几列设置了宽度,则剩余的宽度等分
  • 如果每列都设置了宽度,则按设置的比例分配宽度

表格边框

边框合并

默认 table 是没有边框的,但是一般为了表现效果,我们都会给 table 设置边框,以显示整齐罗列也方便查看。下面我们简单的说下如何给 一个 table 设置边框。

  1. <table>
  2. <thead>
  3. <tr>
  4. <th>1月</th>
  5. <th>2月</th>
  6. <th>3月</th>
  7. <th>4月</th>
  8. </tr>
  9. </thead>
  10. <tbody>
  11. <tr>
  12. <td>31天</td>
  13. <td>28天</td>
  14. <td>31天</td>
  15. <td>30天</td>
  16. </tr>
  17. </tbody>
  18. </table>

首先我们给 table 设置一个 border,代码如下:

table {
    border: 1px solid #ccc;
}

结果发现只有外面一圈有边框,而里面的内容没有 border 来隔开,效果图如下:

image.png

怎么只有外面一层有样式呢?这是因为我们只是使用 CSS 选中了 table 元素,而如果设置里面的线条应该是由 td、th 元素来设置的。现在我们接着设置 th 和 td 的 边框试试:

th, td {
    border: 1px solid #ccc;
}

效果图如下:

image.png

这边框是有了,但是是两层的,于是我们需要重置 table 如下(边框间隙为 0,边框合并):

table {
    border: 1px solid #ccc;
  border-spacing: 0; /* 边框间隙为0 */
  border-collapse: collapse; /* 边框合并 */
}

这样就能达到我们最终的效果了,如下:

image.png

圆角边框

对于圆角来说,一般直接设置 border-radius 为某个值即可,如 5px。但是,我们把这个直接设置在 table 元素上,发现根本没效果,如下:

table {
    border: 1px solid #ccc;
  border-spacing: 0; /* 边框间隙为0 */
  border-collapse: collapse; /* 边框合并 */
  border-radius: 5px; 
}

这是因为合并边框 border-collapse: collapse;border-radius 是相冲的。

既然相冲了,那我们就又拆开吧,再拼成刚才的边框效果,样式如下:

.table-radius {
  border: 1px solid #ccc; /* 整体外围边框 */
  border-radius: 5px;
  border-spacing: 0; /* 边框间隙为0 */
  border-collapse: separate; /* 边框不和合并 */
  overflow: hidden;
}

/* table 已经完成整体外围的边框,那里面格子的边框就由 th 和 td 来拼成*/
.table-radius th,
.table-radius td {
  border-bottom: 1px solid #f00; /* 设置为红色,以区别 table 的边框 */
  border-right: 1px solid #f00;
}

/* 最后一列单元格的右边框与最后一排单元格的下边框需要去掉 */
.table-radius th:last-child,
.table-radius td:last-child {
  border-right: 0;
}

.table-radius tr:last-child td{
  border-bottom: 0;
}

最后效果如下:

image.png

表格滚动

水平滚动

有些时候涉及到一些统计或财务的表格,那宽度超长,这个时候就需要滚动条来滚动显示。

当然表格本身是没有这个滚动功能的,这个时候我们可以再嵌套一个外层,设置外层 wrap 的 overflow-x: scroll;,然后就可以给 table 设置一个超长的宽度,显示数据了。

fixed thead

position 属性有个新值为 sticky,本来就是做这个的好帮手,可惜到目前为止其在 table 上 的表现不是很好。

所以目前还是得用 JS 来搞定,大概的思路是在 table 之外,再搞个只有 thead 的 table,设置定位为 fixed,然后再使用 JS 根据垂直滚动条滚动距离判断显示隐藏。

<!-- 单独的 thead,fixed 定位,默认隐藏,JS 来控制是否显示-->
<table class="table-fixed fixed--head">
  <thead>
    <tr>
      <th>1月</th>
      <th>2月</th>
      <th>3月</th>
      <th>4月</th>
    </tr>
  </thead>
</table>

<!-- 实际的 table -->
<table class="table-fixed">
  <thead>
    <tr>
      <th>1月</th>
      <th>2月</th>
      <th>3月</th>
      <th>4月</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>31天</td>
      <td>28天</td>
      <td>31天</td>
      <td>30天</td>
    </tr>
  </tbody>
</table>