PJCHENder 未整理筆記

[BS] Bootstrap4 Table

2017-10-31

[BS] Bootstrap4 Customize Responsive Table(客制化表格寬度)

@(CSS)[Bootstrap]

tags: table, table-responsive, customization

Table 是報表、數據等資料很常使用的程式方式。在 Bootstrap4 中 Table 的結構其實還蠻單純的,但是有些時候直接套用的表格卻不是這麼的「好看」,它會隨著內容的寬度而對每個欄寬造成不同的影響,進而使得版面變得不太好看,因此,讓我們來試著深入一些些瞭解 Bootstrap Table ,看可以做哪些操作,客制化成我們想要的好看表格。

這篇文章主要說明如何把 Bootstrap 的表格調整成自己想要的樣式,關於 Bootstrap 表格的基本架構可以參考中文官方文件

以下內容建議搭配 範例程式碼 @ CodePen 閱讀。

基本架構

Bootstrap 4 表格的基本架構如下,其他 <th> 標籤可以搭配 scope 屬性使用,屬性值可以是 col, row, colgroup, rowgroup,主要是用來說明這個 th 是屬於某欄或某列的標頭。

另外,Bootstrap 4 還提供其他可套用的 class:

  • <table>: .table-dark, .table-sm, .table-striped, .table-bordered, .table-hover
  • <thead>: .thead-light, .thead-dark
  • <tr>, <td>: .table-active, .table-primary, .table-secondary, .table-success, .table-danger, .table-warning, .table-info, .table-light, .table-dark

HTML <th> scope Attribute @ w3schools

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<!-- HTML -->
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">First Name</th>
<th scope="col">Last Name</th>
<th scope="col">Username</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<td>Mark</td>
<td>Otto</td>
<td>@mdo</td>
</tr>
<tr>
<th scope="row">2</th>
<td>Jacob</td>
<td>Thornton</td>
<td>@fat</td>
</tr>
<tr>
<th scope="row">3</th>
<td>Larry</td>
<td>the Bird</td>
<td>@twitter</td>
</tr>
</tbody>
</table>

響應式表格

.table-responsive 的使用

要達到響應式表格,最直覺想到的是使用在 Bootstrap4 中提供 .table-responsive 這個 class 可以套用在 <table> 外層的 <div> 上:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!-- HTML -->
<div class="table-responsive">
<table class="table table-bordered table-striped">
<caption>List of users</caption>
<thead>
<tr>
<th scope="col">#</th>
<!-- ... -->
<th scope="col">Remark</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<!-- ... -->
<td>Lorem ipsum is placeholder text commonly used in the graphic, print, and publishing industries </td>
</tr>
<tr>
<th scope="row">2</th>
<!-- ... -->
<td>Lorem ipsum is placeholder text commonly used in the graphic, print, and publishing industries </td>
</tr>
</tbody>
</table>
</div>

一般來說只要 Table 內容相較於螢幕尺寸「太多」時,就會自動長出橫軸的 scroll-bar 讓使用者可以拖拉:

Imgur

另外也提供不同尺寸的 .table-responsive 可以使用,如 .table-responsive-sm, .table-responsive-md, .table-responsive-lg, .table-responsive-xl,它們會在該尺寸以下時可以左右滾動;該尺寸以上時則無法(使用的是 max-width)。

.table-responsive-md 為例,當螢幕尺寸 <768px 時,只要表格內容多過螢幕尺寸,就會出現水平捲軸可以滾動;當螢幕尺寸 >= 768px 時,這個水平的滾動捲軸就會消失。

.table-responsive 的作用

從 Bootstrap 的原始碼中,可以看到 .table-responsive 的主要作用是把表格變成 display: block;,當寬度超過時,就以 overflow-x: auto; 來出現水平捲軸:

1
2
3
4
5
6
7
8
/* .table-responsive 的作用 */
.table-responsive {
display: block;
width: 100%;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
-ms-overflow-style: -ms-autohiding-scrollbar;
}

.table-responsive 不足之處

然而,這個基本的 responsive-table 在實際使用上有一些不方便之處,如下圖所示:

  1. 有些表格的標頭會自己換行
  2. 每個欄的寬度不同,看起來不整齊,而且有些欄當中的內容較多時,會一直換行

Imgur

解決文字換行的問題

第一個問題比較容易解決,可以用 Bootstrap 中提供的 .text-nowrap 來避免表格欄位標頭換行即可。

1
2
<th scope="col" class="text-nowrap">First Name</th>
<th scope="col" class="text-nowrap">Last Name</th>

客制化表格(Customization Bootstrap Table)

第二個問題則需要透過客制化的表格來處理,根據實際的內容調整表格寬度,做出最合適的表格:

  1. 在原本的 .col 這行加上 .custom-table-width(名字可以自己取),並且設為 overflow-x: auto;
1
2
3
4
5
6
<!-- HTML -->
<div class="col custom-table-width">
<table class="table">
...
</table>
<div>
1
2
3
4
.custom-table-width {
overflow-x: auto;
...
}

2.雖然設定了 overflow: auto;,但是原本在 .col 中預設 padding 的空間一樣會顯示內容出來,造成表格的寬度和上下文的寬度有 15px 的差異,因此我們需要使用 margin 把原本左右的空間推回來:

1
2
3
4
5
6
7
8
9
10
// SCSS
$grid-gutter-width: 30px;

.custom-table-width {
overflow-x: auto;
margin-right: $grid-gutter-width / 2; // 利用 margin 推回去原本 padding 的空間
margin-left: $grid-gutter-width / 2;
padding-right: 0;
padding-left: 0;
}

Bootstrap 預設的 padding 寬度是 15px ,也就是欄間距(gutters)除以 2 的寬度( $grid-gutter-width / 2)。

3.可以把 .table-responsive 拿掉,因為裡面的 display: block 屬性可能使得表格無法按照給定的寬度顯示。
4.將 .table 設定 table-layoutmin-width
table-layout 的預設值是 auto,也就是表格和細格(cell)的寬度會根據內容而改變;為了要讓表格根據所設定的值而改變,要設成 fixed,設定後表格的各欄寬度就會相同。另外,為了確保字不會疊在一起,或不斷換行,需要為表格設定最小寬度(min-width),這裡可以根據表格內容多寡設定一個適合的最小寬度:

1
2
3
4
.table {
table-layout: fixed; // 表格和欄寬將根據所給定的寬度來顯示
min-width: 1440px; // 避免因寬度不足而字疊在一起(根據表格內容設定寬度)
}

Imgur

設定了 table-layout: fixed 後,表格各欄就會等寬(table-layout @ MDN)。

5.最後要設定表格中各欄的寬度,這裡一種作法是直接在 <th width="10%"> 加上 width 屬性,但 MDN 並不建議這種作法,因為 width 屬性在 HTML 5 中已被移除,建議還是在 CSS 中定義各欄寬,寬度可以設定%, px, em, rem 等等都可以,如果想要給到比較精確的話可以使用 pxem/rem

HTML th element @ MDN

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 流水號 #
thead th:first-child,
tbody td:first-child {
width: 2em;
}

// Time
thead th:nth-child(10),
tbody td:nth-child(10) {
width: 13em;
}

// Remark
thead th:last-child,
tbody td:last-child {
width: 20%;
}

完整範例程式碼

HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<!-- HTML -->
<div class="container">
<div class="row">
<div class="col custom-table-width">
<h4>Table with custom width</h4>
<table class="table table-bordered table-striped">
<caption>List of users</caption>
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">First Name</th>
<th scope="col">Last Name</th>
<th scope="col">Username</th>
<th scope="col">Height</th>
<th scope="col">Width</th>
<th scope="col">Degree</th>
<th scope="col">Country</th>
<th scope="col">Major</th>
<th scope="col">Time</th>
<th scope="col">Remark</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<td>Mark</td>
<td>Otto</td>
<td>@mdo</td>
<td>171</td>
<td>64</td>
<td>Master</td>
<td>Taiwan</td>
<td>Psychology</td>
<td>2017-10-21 16:43:20</td>
<td>Lorem ipsum is placeholder text commonly used in the graphic, print, and publishing industries </td>
</tr>
<tr>
<th scope="row">2</th>
<td>Jacob</td>
<td>Thornton</td>
<td>@fat</td>
<td>171</td>
<td>64</td>
<td>Master</td>
<td>Taiwan</td>
<td>Psychology</td>
<td>2017-10-21 16:43:20</td>
<td>Lorem ipsum is placeholder text commonly used in the graphic, print, and publishing industries </td>
</tr>
<tr>
<th scope="row">3</th>
<td>Larry</td>
<td>the Bird</td>
<td>@twitter</td>
<td>171</td>
<td>64</td>
<td>Master</td>
<td>Taiwan</td>
<td>Psychology</td>
<td>2017-10-21 16:43:20</td>
<td>Lorem ipsum is placeholder text commonly used in the graphic, print, and publishing industries </td>
</tr>
</tbody>
</table>
</div>
</div>
</div>

SCSS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// 定義各欄位的寬度
$grid-gutter-width: 30px;
.custom-table-width {
overflow-x: auto;
margin-right: $grid-gutter-width / 2; // 利用 margin 推回去原本 padding 的空間
margin-left: $grid-gutter-width / 2;
padding-right: 0;
padding-left: 0;

.table {
table-layout: fixed; // 表格和欄寬將根據所給定的寬度來顯示(預設等寬)
min-width: 1440px; // 避免因寬度不足而字疊在一起
}

// 流水號 #
thead th:first-child,
tbody td:first-child {
width: 2em;
}

// Time
thead th:nth-child(10),
tbody td:nth-child(10) {
width: 13em;
}

// Remark
thead th:last-child,
tbody td:last-child {
width: 20%;
}
}

如此就可以客制化出自己想要的表格寬度和欄寬:

Imgur

其他客制化內容

表格內容垂直置中

1
2
3
.table th, .table td{
vertical-align: middle
}

標頭邊框寬

當我們使用 .table-bordered 時,會發現標頭 <thead><tbody> 之間的邊框稍微比較寬一些,這是因為在 Bootstrap 中預設標頭的邊框底寬是 2px ,如果你希望它的寬度不要不一樣,可以使用:

1
2
3
4
.table-bordered thead th,
.table-bordered thead td {
border-bottom-width: 1px;
}

Imgur

關於本文若有錯誤,敬請告知,避免錯誤或不正確的資訊傳播。若有其他建議的作法,也歡迎告知一同討論。

延伸閱讀

掃描二維條碼,分享此文章