我最近注意到一個小悖論:很多年前——在 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;
}

……我們得到:

border-collapse 設定為折疊

如果我們然後將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-width1px ,您可以在懸停時將<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;
}

對所有列重複此操作。


結論

表格樣式指南到此結束。

我沒有介紹colspanrowspanscopespan 。如果您想更深入地了解這些內容,我建議您閱讀有關表的 MDN 頁面

示範

我在這裡製作了一個包含大量演示的 CodePen:

https://codepen.io/stoumann/pen/RwdVxJM


原文出處:https://dev.to/madsstoumann/a-guide-to-styling-tables-28d2


共有 0 則留言