我最近注意到一個小悖論:很多年前——在 CSS 網格出現之前——我們使用<table>
來模擬網格佈局。現在我們有了網格佈局,我們用它們來模擬表格!這是錯誤的。表格用於表格資料;在一堆<div>
中呈現表格資料是沒有意義的。
造成這種弊端的原因可能是因為表格的樣式可能有點棘手,而且大多數 CSS 框架使用border-collapse: collapse
作為預設的表格樣式。正如我們將在本教程中看到的,折疊邊框對於表格樣式並不總是有用。
讓我們研究一下<table>
的元素,然後了解如何建立它們並設定它們的樣式。
除了<table>
元素本身之外,您只需要這 3 個標籤來建立基本表格:
標籤 | 描述 |
---|---|
td |
表資料單元 |
th |
表格標題儲存格 |
tr |
表行 |
例子:
<table>
<tr><th>Header</th></tr>
<tr><td>Content</td></tr>
</table>
但是,為了更好地構造表,我們可以將行封裝在:
標籤 | 描述 |
---|---|
thead |
表頭 |
tbody |
桌體 |
tfoot |
表頁腳 |
最後,我們可以在表格中新增<caption>
,並在<colgroup>
內的<col>
標籤中定義列。
例子:
<table>
<caption>Super Heroes</caption>
<colgroup><col><col><col><col></colgroup>
<thead>
<tr><th>First Name</th><th>Last Name</th><th>Known As</th><th>Place</th></tr>
</thead>
<tbody>
<tr><td>Bruce</td><td>Wayne</td><td>Batman</td><td>Gotham City</td></tr>
<tr><td>Clark</td><td>Kent</td><td>Superman</td><td>Metropolis</td></tr>
<tr><td>Tony</td><td>Stark</td><td>Iron Man</td><td>Malibu</td></tr>
<tr><td>Peter</td><td>Parker</td><td>Spider-Man</td><td>New York City</td></tr>
<tr><td>Matt</td><td>Murdock</td><td>Daredevil</td><td>New York City</td></tr>
</tbody>
</table>
如果沒有任何樣式,您的瀏覽器將呈現以下內容:
預設的用戶代理樣式是:
table {
border-collapse: separate;
text-indent: initial;
border-spacing: 2px;
}
現在,如果我們加入一個超級簡單的規則:
:is(td,th) {
border-style: solid;
}
我們得到:
注意單獨的邊框。看起來不太好看...
因此,為了了解折疊邊框的流行(以及更好的字體!),如果我們簡單地加入:
table {
border-collapse: collapse;
font-family: system-ui;
}
……我們得到:
如果我們然後將padding: .5ch 1ch
加入我們的:is(td,th)
選擇器並將margin-block: 1rlh
加入<caption>
,我們會得到:
回顧一下,我們需要得到上述樣式的是:
table {
border-collapse: collapse;
font-family: system-ui;
& caption { margin-block: 1rlh; }
&:is(td, th) {
border-style: solid;
padding: .5ch 1ch;
}
}
若要將<caption>
放置在表格下方,請使用:
table {
caption-side: bottom;
}
要為columns加入奇數/偶數斑馬條紋,我們可以簡單地設定<col>
標籤的樣式:
col:nth-of-type(even) { background: #F2F2F2; }
對於行,它是類似的:
tr:nth-of-type(odd) { background: #F2F2F2; }
圓角有點棘手。您不能只將border-radius
新增至<table>
,因此我們必須定位第一行和最後一行的第一個和最後一個儲存格:
th {
&:first-of-type { border-start-start-radius: .5em }
&:last-of-type { border-start-end-radius: .5em }
}
tr {
&:last-of-type {
& td {
&:first-of-type { border-end-start-radius: .5em }
&:last-of-type { border-end-end-radius: .5em }
}
}
}
……但仍然沒有發生任何事情!那是因為:
如果您的表格有折疊邊框,則無法新增
border-radius
。
因此,我們必須使用單獨的邊框,並模仿折疊的邊框:
table {
border-spacing: 0;
}
:is(td, th) {
border-block-width: 1px 0;
border-inline-width: 1px 0;
&:last-of-type { border-inline-end-width: 1px }
}
現在我們有了圓角:
讓我們保留單獨的列,並使用border-spacing
屬性在列之間新增間隙:
table {
border-spacing: 2ch 0;
& :is(td, th) {
border-inline-width: 1px;
}
}
我們甚至可以加入border-radius
:
這仍然只是一個<table>
,但如果用作“比較表”,則更具可讀性。
對於分割行,我們只需要更新border-spacing
屬性的第二部分(y 軸):
table {
border-spacing: 0 2ch;
& :is(td, th) {
border-block-width: 1px;
}
}
對於大桌子,準確了解您所在的位置非常重要。為此,我們需要:hover
,並且 - 如果您使用的是鍵盤可導航的表格 - :focus-visble
-styles。
在此範例中,懸停樣式會套用於<col>
、 <tr>
和<td>
:
懸停行和單元格很簡單:
td:hover {
background: #666666;
}
tr:hover {
background: #E6E6E6;
}
將滑鼠懸停在<col>
上有點複雜。
您可以新增一條規則:
col:hover {
background: #E6E6E6;
}
...但這不起作用。奇怪的是,如果您在開發工具中選擇一個 col-element 並為其啟用:hover
,它會起作用 - 但在 IRL 中不起作用。
相反,我們需要使用:has
捕獲單元格的懸停,然後設定<col>
元素的樣式:
table {
&:has(:is(td,th):nth-child(1):hover col:nth-child(1) {
background: #E6E6E6;
}
發生什麼事了?
讓我們來分解一下:
如果我們的表格有一個<td>
或<th>
,它是nth-child(1)
並且當前懸停,則選擇具有相同nth-child
選擇器的<col>
,並設定它的background
。
唷! ……並且您需要為每一列重複此程式碼: nth-child(2)
、 nth-child(3)
等。
在懸停時顯示輪廓也很簡單,單元格和行也是如此。您需要從偏移量中扣除寬度:
:is(td, th, tr):hover {
outline: 2px solid #666;
outline-offset: -2px;
}
概述一列非常棘手,但看起來不錯:
如果單元格的border-width
為1px
,您可以在懸停時將<col>
的border-width
設為2px
,但隨後整個表格會發生變化。
Álvaro Montoro 建議在<col>
上使用背景漸變來模擬邊框,如果表格單元格是透明的,效果很好。
為了使其與border-radius
一起工作並保留單元格可能具有的任何背景,我最終為每個單元格使用了一個偽元素:
:is(td,th) {
position: relative;
&::after {
border-inline: 2px solid transparent;
border-radius: inherit;
content: '';
inset: -2px 0 0 0;
position: absolute;
}
}
tr:first-of-type th::after {
border-block-start: 2px solid transparent;
}
tr:last-of-type td::after {
border-block-end: 2px solid transparent;
}
……然後,與我們對 col-hover 所做的類似,在懸停時將所有單元格定位為具有相同的“col-index”:
:has(:is(td,th):nth-child(1):hover :is(td,th):nth-child(1) {
border-color: #666;
}
對所有列重複此操作。
在舊規範中,您可以為<col>
元素新增align
屬性。那不再起作用了。
範例:您想要將第二列中的文字置中並右對齊第四列中的文字:
我們可以在表本身中新增每列的資料屬性,而不是在每個單元格中新增一個類別:
<table data-c2="center" data-c4="end">
然後,在 CSS 中:
[data-c2~="center"] tr > *:nth-of-type(2) {
text-align: center;
}
[data-c4~="end"] tr > *:nth-of-type(4) {
text-align: end;
}
對所有列重複此操作。
表格樣式指南到此結束。
我沒有介紹colspan
、 rowspan
、 scope
和span
。如果您想更深入地了解這些內容,我建議您閱讀有關表的 MDN 頁面。
我在這裡製作了一個包含大量演示的 CodePen:
https://codepen.io/stoumann/pen/RwdVxJM
原文出處:https://dev.to/madsstoumann/a-guide-to-styling-tables-28d2