TailwindCSS 表格與清單:table、list 響應式排版全解 | TailwindCSS 完整教學
上一篇讓元素「動起來、變好看」,這一篇要把視線轉向內容本身的結構化呈現。TailwindCSS 的表格與清單工具,涵蓋
border-collapse/border-separate(邊框合併或分離)、border-spacing(儲存格間距)、table-layout(table-auto/table-fixed決定欄寬策略)、caption-side(表格說明位置),以及清單的list-style-type(項目符號樣式)、list-inside/list-outside(符號位置)、list-image(自訂圖片符號)。搭配overflow-x-auto、divide-y、truncate這些老朋友,你就能打造出既專業又響應式的資料表與美化清單——讓內容從「能看」升級到「好讀」。
前言
上一篇 《過渡與動畫》 我們替互動效果補上了「時間」這個維度,讓 hover、載入、進場都流暢起來。到這裡,讓「單一元素」動起來、變好看的視覺工具你已大致掌握。這一篇 表格與清單(Tables & Lists),我們要把焦點從「元素美化」轉向「內容排版」——如何把一堆資料整整齊齊地排進表格,如何把重點條列成一份清晰的清單。這是每個實際專案都躲不掉的需求:後台的用戶列表、訂單表、財報數字、功能對照表、待辦清單……全都靠這一組工具撐起來。
先用一個生活化的類比建立心智模型。表格就像一張 Excel 試算表:你要決定欄與欄之間、列與列之間的格線要「合併成一條共用線」還是「各自獨立留白」(這就是 border-collapse vs border-separate);要決定欄寬是「內容多寬欄就多寬」還是「先切好固定比例再塞內容」(這就是 table-auto vs table-fixed);還要決定那句說明文字掛在表格頭上還是腳下(caption-side)。而清單就像一份手寫的重點筆記:每一項前面的符號是實心圓點、數字、還是你自訂的勾勾圖示(list-style-type、list-image),符號要縮進文字裡還是凸出在外(list-inside vs list-outside)。把這兩個類比記住,後面所有 class 都只是在調這幾個旋鈕。
本系列以 TailwindCSS v4 為預設版本。表格與清單這組工具在 v4 補齊了不少過去要靠任意值才能寫的 utility。本篇你將學到:
- 表格邊框與間距:
border-collapse/border-separate、border-spacing-*(含 x/y 方向)如何決定格線與留白 - 表格佈局與說明:
table-auto/table-fixed的欄寬差異、caption-top/caption-bottom的表格說明位置 - 清單樣式:
list-disc/list-decimal/list-none、list-inside/list-outside、list-image-*自訂圖片符號 - 實務排版技巧:用
overflow-x-auto做響應式表格、divide-y取代逐列邊框、table-fixed+truncate控制長文字
本系列以 TailwindCSS v4 為預設版本,範例皆可直接執行。凡涉及 v3 差異之處,我會特別標註。
核心概念
表格與清單工具的分類全景
Tailwind 針對「內容結構」的 utility 主要分成 表格(table) 與 清單(list) 兩大群組。下表先建立全景,涵蓋每個工具的代表 class 與對應 CSS:
| 群組 | 分類 | 代表 utility | 對應 CSS | 作用 |
|---|---|---|---|---|
| 表格 | 邊框模型 | border-collapse、border-separate | border-collapse | 格線合併共享/各儲存格獨立 |
| 表格 | 邊框間距 | border-spacing-2、border-spacing-x-4、border-spacing-y-2 | border-spacing | 分離模式下儲存格間的留白 |
| 表格 | 佈局 | table-auto、table-fixed | table-layout | 欄寬由內容決定/由設定固定 |
| 表格 | 說明位置 | caption-top、caption-bottom | caption-side | <caption> 在表格上方/下方 |
| 表格 | 顯示模式 | table、table-cell、table-row、table-row-group | display | 讓非表格元素以表格模式渲染 |
| 清單 | 符號樣式 | list-none、list-disc、list-decimal | list-style-type | 無符號/實心圓/數字 |
| 清單 | 符號位置 | list-inside、list-outside | list-style-position | 符號在文字流內/流外 |
| 清單 | 圖片符號 | list-image-none、list-image-[url(...)] | list-style-image | 用圖片取代預設項目符號 |
不用一次背完。核心心智模型有三句話:表格的靈魂是兩組二選一——邊框「合併還是分離」(border-collapse/border-separate)、欄寬「隨內容還是固定」(table-auto/table-fixed);清單的靈魂是三個旋鈕——符號長什麼樣(list-* 型別)、符號縮進還是凸出(inside/outside)、要不要換成圖片(list-image-*);至於響應式,靠的不是專屬 class,而是 overflow-x-auto 這類佈局工具去包住表格。 抓住這三點,其餘都是刻度與命名細節。
表格的兩組核心二選一
表格的視覺與行為,幾乎由兩組互斥的選擇決定,理解它們你就掌握了八成:
- 邊框模型:
border-collapsevsborder-separate。border-collapse(合併)讓相鄰儲存格共享同一條邊框線,畫出來就是傳統那種「格線只有一像素、緊密相連」的資料表,是最常見的做法。border-separate(分離)則讓每個儲存格擁有各自獨立的邊框,儲存格之間可以留白——這個留白就靠border-spacing-*控制。一個關鍵限制:border-collapse模式下,個別儲存格無法套用圓角(rounded),因為邊框被共享了;要做圓角得改用border-separate,或把圓角做在外層容器上。 - 欄寬策略:
table-autovstable-fixed。table-auto(預設)讓欄寬「由內容決定」——哪一欄內容最寬,那一欄就多寬,適合內容長度不固定、想讓表格自然撐開的情境。table-fixed(固定)則讓欄寬「由設定決定」——第一列或<colgroup>裡<col>的寬度說了算,之後不管內容多長都不會再撐開欄位。table-fixed是讓truncate(文字截斷成…)生效的必要前提,這點是初學最常踩的坑,稍後會專門講。
除了這兩組,border-spacing-* 提供了 border-spacing-2(全方向 8px)、border-spacing-x-4(僅水平)、border-spacing-y-2(僅垂直)等刻度,只在 border-separate 模式下才有意義。而 caption-top/caption-bottom 則對應 CSS 的 caption-side,控制語義化的 <caption> 標題顯示在表格上方還是下方——資料來源、註記這類文字常放在 caption-bottom。
清單的三個旋鈕:型別、位置、圖片
清單相對單純,記住三個旋鈕就夠:
- 符號型別(
list-style-type):list-none(無符號,常用於自訂項目符號或導覽列)、list-disc(實心圓,<ul>的預設)、list-decimal(數字,<ol>的預設)。若要更特殊的編號樣式(羅馬數字、小寫字母),用任意值list-[upper-roman]、list-[lower-alpha]。 - 符號位置(
list-style-position):list-outside(預設,符號凸出在文字區塊外,多行文字會對齊第一行的文字而非符號)、list-inside(符號縮進到文字流內,換行時第二行會從最左邊起排、符號佔一格位置)。一個容易忽略的細節:list-disc/list-decimal的符號預設在list-outside位置,若父層有 padding 或 overflow,符號可能被裁掉看不見——這時改list-inside或給清單留左邊距即可。 - 圖片符號(
list-style-image):list-image-none(無圖片,回退到型別符號)、list-image-[url('/icons/check.svg')](用任意值指定圖片當每一項的項目符號)。這比「list-none+::before偽元素」的傳統做法簡潔許多,適合快速把圓點換成品牌勾勾圖示。
v4 差異:補齊 border-spacing、list-image、caption
這組工具在 v4 有幾個重要補強,若你看舊教學或維護 v3 專案要特別注意:
border-spacing-*:v4 正式加入完整的border-spacing刻度(含 x/y 方向),v3 時代得靠任意值[border-spacing:0.5rem]或自訂 class 才能寫。list-image-*:v4 加入list-image-none這個 class 以及list-image-[url(...)]任意值支援,v3 對圖片符號的支援較弱。caption-top/caption-bottom:v4 完整加入這兩個 utility,v3 同樣需要任意值[caption-side:bottom]。
除此之外,表格與清單的核心 utility(border-collapse、table-fixed、list-disc 等)在 v3、v4 用法一致,可以放心沿用。
一個常被忽略的夥伴:display table 系列
除了直接用 <table> 標籤,Tailwind 也提供了一整組 display 為表格模式的 utility:table、table-cell、table-row、table-row-group(對應 <tbody>)、table-header-group(<thead>)、table-column(<col>)等。它們的用途,是讓非 <table> 的元素也能借用表格的排版行為。最經典的應用是「垂直置中」——在 Flexbox 與 Grid 普及之前,table-cell + align-middle 是讓內容垂直居中的老招;如今雖然多半改用 flex items-center,但在某些需要「多欄等高、內容自動對齊」的場景,這組 display utility 仍有一席之地。初學階段不必深究,只要知道「表格排版不一定要用 <table> 標籤,display: table 系列能把任何容器變成表格佈局」即可,遇到特殊需求時再回頭查表。
實作範例
理論看完,我們用三個高頻範例把「美化資料表、響應式表格、自訂清單」串起來。以下都是完整的 HTML + Tailwind,可直接貼進頁面觀察效果。
範例一:美化資料表(斑馬紋 + hover 高亮)
後台管理最常見的就是一張專業感十足的資料表。這裡示範 border-collapse 合併邊框、divide-y 逐列分隔線、斑馬紋(even:)、hover 高亮的組合,並用外層容器做圓角:
<!-- 外層容器負責圓角與邊框;overflow-x-auto 保底響應式 -->
<div class="overflow-x-auto rounded-xl border border-gray-200">
<table class="w-full text-sm text-left border-collapse">
<thead>
<tr class="bg-gray-50 border-b border-gray-200">
<th class="px-6 py-4 text-xs font-semibold text-gray-500 uppercase tracking-wider">用戶名稱</th>
<th class="px-6 py-4 text-xs font-semibold text-gray-500 uppercase tracking-wider">電子郵件</th>
<th class="px-6 py-4 text-xs font-semibold text-gray-500 uppercase tracking-wider">角色</th>
<th class="px-6 py-4 text-xs font-semibold text-gray-500 uppercase tracking-wider">狀態</th>
</tr>
</thead>
<!-- divide-y 自動在每列之間畫分隔線,免去逐列加 border-bottom -->
<tbody class="divide-y divide-gray-100">
<tr class="even:bg-gray-50 hover:bg-cyan-50 transition-colors cursor-pointer">
<td class="px-6 py-4 font-medium text-gray-900">陳小明</td>
<td class="px-6 py-4 text-gray-600">chen@example.com</td>
<td class="px-6 py-4">
<span class="px-2 py-1 text-xs font-medium bg-cyan-50 text-cyan-700 rounded-full">管理員</span>
</td>
<td class="px-6 py-4">
<span class="flex items-center gap-1.5 text-green-700">
<span class="size-2 rounded-full bg-green-500"></span>啟用
</span>
</td>
</tr>
<tr class="even:bg-gray-50 hover:bg-cyan-50 transition-colors cursor-pointer">
<td class="px-6 py-4 font-medium text-gray-900">林美華</td>
<td class="px-6 py-4 text-gray-600">lin@example.com</td>
<td class="px-6 py-4">
<span class="px-2 py-1 text-xs font-medium bg-gray-100 text-gray-600 rounded-full">一般用戶</span>
</td>
<td class="px-6 py-4">
<span class="flex items-center gap-1.5 text-gray-500">
<span class="size-2 rounded-full bg-gray-400"></span>停用
</span>
</td>
</tr>
</tbody>
</table>
</div>
這個範例濃縮了好幾個實務要點。第一,圓角做在外層容器:<table> 用了 border-collapse,個別儲存格無法圓角,所以圓角交給外層 <div> 的 rounded-xl overflow-hidden(這裡用 overflow-x-auto 一併達成裁切與響應式)。第二,divide-y divide-gray-100 取代逐列邊框:只要加在 <tbody> 上,Tailwind 就會自動在每一列之間畫一條淺色分隔線,比每個 <tr> 都加 border-b 乾淨得多。第三,even:bg-gray-50 做斑馬紋:偶數列自動加淺灰底,長表格更好讀。第四,hover:bg-cyan-50 transition-colors 讓滑鼠移過的那一列高亮,配合上一篇學的過渡讓變色滑順。狀態欄則用「小圓點 + 文字」的組合,是後台表格標示啟用/停用的招牌寫法——綠點配「啟用」、灰點配「停用」,一眼就能辨識,比純文字更直覺。值得一提的是,表頭用 text-xs uppercase tracking-wider text-gray-500 這組樣式做出「小字、全大寫、加寬字距、淺灰」的視覺,是現代後台表格公認最有質感的表頭寫法,把它記成一個固定搭配即可。
範例二:響應式表格 + 固定佈局截斷(table-fixed + truncate)
表格 RWD 的保底做法是 水平捲動,同時示範 table-fixed 搭配 truncate 如何把過長內容裁成 …,以及用 hidden md:table-cell 在小螢幕隱藏次要欄:
<!-- overflow-x-auto 讓窄螢幕能左右捲動,資料不破版 -->
<div class="overflow-x-auto rounded-xl border border-gray-200">
<table class="w-full table-fixed border-collapse text-sm">
<!-- colgroup 明確分配欄寬,table-fixed 才能鎖定欄位 -->
<colgroup>
<col class="w-1/2">
<col class="w-1/4">
<col class="w-1/4">
</colgroup>
<thead class="bg-gray-50 border-b border-gray-200">
<tr>
<th class="px-4 py-3 text-left text-xs font-semibold text-gray-500 uppercase">商品名稱</th>
<!-- 次要欄:md 以下隱藏,小螢幕先讓路 -->
<th class="hidden md:table-cell px-4 py-3 text-left text-xs font-semibold text-gray-500 uppercase">類別</th>
<th class="px-4 py-3 text-right text-xs font-semibold text-gray-500 uppercase">金額</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-100">
<tr>
<!-- truncate 需要 table-fixed + 固定欄寬才會生效 -->
<td class="px-4 py-3 truncate font-medium text-gray-900">
非常非常長的商品名稱,超過欄寬之後會被截斷顯示成省略號
</td>
<td class="hidden md:table-cell px-4 py-3 text-gray-600">電子產品</td>
<td class="px-4 py-3 text-right font-medium text-gray-900">NT$5,600</td>
</tr>
<tr>
<td class="px-4 py-3 truncate font-medium text-gray-900">藍牙耳機</td>
<td class="hidden md:table-cell px-4 py-3 text-gray-600">配件</td>
<td class="px-4 py-3 text-right font-medium text-gray-900">NT$1,290</td>
</tr>
</tbody>
</table>
</div>
這個範例把「響應式」與「固定佈局」兩個重點綁在一起。overflow-x-auto 是響應式的第一道防線:不管表格多寬,窄螢幕都能左右捲動看完整內容,資料完整性優先。table-fixed + <colgroup> 鎖定欄寬:三欄被固定成 1/2、1/4、1/4 的比例,之後內容再長也不會撐開欄位——這正是 truncate 能生效的前提。若你把 table-fixed 拿掉(回到預設的 table-auto),第一格那串長名稱就會把整欄撐爆、truncate 完全失效,這是新手最常見的困惑。hidden md:table-cell 做優先欄隱藏:類別欄在手機(md 以下)隱藏、平板以上才出現,注意 <th> 和對應的 <td> 要成對加同一組 class,否則表頭與內容會錯位。
範例三:自訂清單與帶 caption 的小表
最後把清單的三種寫法一次收齊——自訂勾勾清單、標準有序清單、list-image 圖片符號,並附一個帶 caption-bottom 的迷你表格:
<!-- 1. 自訂勾勾清單:list-none + flex 排版,最靈活 -->
<ul class="space-y-3">
<li class="flex items-start gap-3">
<svg class="mt-0.5 size-5 text-green-500 flex-none" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
</svg>
<span class="text-gray-700">支援所有主流瀏覽器,響應式完整</span>
</li>
<li class="flex items-start gap-3">
<svg class="mt-0.5 size-5 text-red-400 flex-none" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
</svg>
<span class="text-gray-500">不支援已停止更新的舊瀏覽器</span>
</li>
</ul>
<!-- 2. 標準有序清單:list-decimal + list-inside -->
<ol class="list-decimal list-inside space-y-2 text-gray-700">
<li>開啟終端機</li>
<li>執行 <code class="px-1.5 py-0.5 bg-gray-100 rounded text-sm">npm install</code></li>
<li>執行 <code class="px-1.5 py-0.5 bg-gray-100 rounded text-sm">npm run dev</code></li>
</ol>
<!-- 3. list-image:用圖片直接當項目符號 -->
<ul class="list-image-[url('/icons/check.svg')] list-inside space-y-2 text-gray-700">
<li>自動套用圖片作為每一項的符號</li>
<li>比 list-none + ::before 偽元素更簡潔</li>
</ul>
<!-- 4. 帶 caption 的小表:caption-bottom 放資料來源 -->
<table class="w-full border-collapse text-sm">
<caption class="caption-bottom pt-3 text-xs text-gray-500 text-left">
資料來源:2026 年第二季財報
</caption>
<thead class="bg-gray-50 border-b border-gray-200">
<tr>
<th class="px-4 py-2 text-left font-semibold text-gray-500">項目</th>
<th class="px-4 py-2 text-right font-semibold text-gray-500">金額</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-100">
<tr>
<td class="px-4 py-2 text-gray-900">營收</td>
<td class="px-4 py-2 text-right font-medium text-gray-900">NT$12,000,000</td>
</tr>
</tbody>
</table>
這個範例展示清單的三種層次。自訂勾勾清單用 list-none(其實這裡連 <ul> 的預設符號都不需要,直接靠 flex 排版)+ flex items-start gap-3 把 SVG 圖示與文字並排,flex-none 確保圖示不被壓縮、mt-0.5 讓圖示與第一行文字對齊——這是功能對照、優缺點列表最靈活的做法,因為每一項的圖示顏色(綠勾、紅叉)都能獨立控制。標準有序清單用 list-decimal list-inside,數字符號縮進在文字流內,適合步驟教學。list-image 清單則直接用 list-image-[url(...)] 任意值把符號換成圖片,一行 class 搞定,不必寫偽元素。最後的小表格示範 caption-bottom:<caption> 是表格語義化的標題元素,caption-bottom 讓它顯示在表格下方,最適合放「資料來源」「更新時間」這類註記。
常見錯誤與最佳實踐
四個最容易踩的表格與清單坑
坑一:truncate 在 table-auto 下無效,文字永遠不截斷。 期望長文字裁成 …,結果整欄被撐爆。原因:預設 table-auto 的欄寬由內容決定,truncate 的 white-space: nowrap 會讓欄位一路變寬把文字塞下,ellipsis 永遠不觸發。根治法:改用 table-fixed 並用 <colgroup> 或 <th> 明確設定欄寬。
<!-- ❌ table-auto(預設)下 truncate 無效,欄位被撐爆 -->
<table class="w-full">
<tr><td class="truncate">很長很長的文字不會被截斷</td></tr>
</table>
<!-- ✅ table-fixed + 固定欄寬,truncate 才生效 -->
<table class="w-full table-fixed">
<colgroup><col class="w-1/2"></colgroup>
<tr><td class="truncate">很長很長的文字會被截斷成…</td></tr>
</table>
坑二:border-collapse 表格對儲存格加 rounded 沒效果。 想做圓角表格,直接在 <td> 加 rounded-xl 卻毫無變化。原因:合併邊框模式下相鄰儲存格共享邊框,個別圓角無法渲染。根治法:把圓角做在外層容器(rounded-xl overflow-hidden),或改用 border-separate 對每列頭尾儲存格加 rounded-l-*/rounded-r-*。
<!-- ✅ 整張表外框圓角:交給外層容器 -->
<div class="rounded-xl overflow-hidden border border-gray-200">
<table class="w-full border-collapse">...</table>
</div>
<!-- ✅ 逐列卡片圓角:改用 border-separate + border-spacing-y-* -->
<table class="w-full border-separate border-spacing-y-2">
<tbody>
<tr class="bg-white shadow-sm">
<td class="px-6 py-4 rounded-l-xl">訂單 #1234</td>
<td class="px-6 py-4 rounded-r-xl text-right">NT$3,200</td>
</tr>
</tbody>
</table>
坑三:對表格元素加 margin,完全沒反應。 想用 m-4 撐開儲存格間距,卻發現毫無變化。原因:<td>/<th> 等表格元素不接受 margin(CSS 表格盒模型限制)。根治法:儲存格內部留白一律用 padding(px-*/py-*);儲存格「之間」的留白用 border-separate + border-spacing-*。
<!-- ❌ td 不接受 margin -->
<td class="m-4">...</td>
<!-- ✅ 內部留白用 padding;格間留白用 border-spacing -->
<td class="px-6 py-4">...</td>
坑四:手機表格直接破版,沒有任何響應式防護。 一張寬表格塞進手機就溢出畫面、擠壓變形。原因:表格內容天生比手機寬。根治法:務必用 overflow-x-auto 的容器包住表格當保底,再視情況用 hidden md:table-cell 隱藏次要欄。
<!-- ✅ 保底:外層容器 overflow-x-auto,窄螢幕可捲動 -->
<div class="overflow-x-auto">
<table class="w-full min-w-[640px] border-collapse">...</table>
</div>
表格與清單最佳實踐清單
- 表格一律用
overflow-x-auto容器包住:這是響應式的保底防線,避免手機破版。 - 逐列分隔線用
divide-y:加在<tbody>上,比每個<tr>手動加border-b乾淨。 - 圓角做在外層容器:
border-collapse表格的圓角交給rounded-xl overflow-hidden的父層,別加在儲存格上。 - 要截斷長文字先切
table-fixed:搭配<colgroup>設定欄寬,truncate才會生效。 - 儲存格留白用
padding不用margin:表格元素不吃margin,格間留白改用border-spacing。 - 卡片式列表用
border-separate+border-spacing-y-*:讓每一列變成有間距、可圓角的獨立卡片。 - 清單符號被裁掉時改
list-inside:或給清單容器留左邊距,避免list-outside的符號被 padding/overflow 吃掉。 - 功能對照清單用
list-none+ flex:每項圖示顏色可獨立控制,比list-image更靈活。
小結
這是 TailwindCSS 完整教學 系列的第二十二篇。上一篇 《過渡與動畫》 讓單一元素動了起來、變得流暢;而這一篇我們把視線從「元素美化」轉向「內容排版」——用表格與清單工具,把資料整齊地排進格子、把重點清楚地條列出來,完成了從「讓元素好看」到「讓內容好讀」的過渡。回顧幾個重點:
- 表格兩組核心二選一:邊框「合併」(
border-collapse)或「分離」(border-separate+border-spacing-*);欄寬「隨內容」(table-auto)或「固定」(table-fixed,也是truncate生效前提)。 - 表格說明位置:
caption-top/caption-bottom對應caption-side,資料來源常放caption-bottom。 - 清單三個旋鈕:符號型別(
list-disc/list-decimal/list-none)、符號位置(list-inside/list-outside)、圖片符號(list-image-*)。 - 實務排版技巧:
overflow-x-auto做響應式保底、divide-y取代逐列邊框、外層容器做圓角、hidden md:table-cell隱藏次要欄。 - v4 差異:
border-spacing-*、list-image-*、caption-top/caption-bottom都是 v4 補齊的完整 utility,v3 需靠任意值。
到這裡,讓內容「排得整齊、讀得順暢」的結構化工具你已掌握。接下來我們要把焦點轉向使用者與畫面的「互動」——游標長什麼樣、能不能選取文字、捲動要不要平滑、觸控時的行為又該如何調整。下一篇 《互動性》 會帶你認識 cursor-*、select-*、scroll-*、touch-* 等一組讓介面「用起來更順手」的 utility,從「讓內容好讀」再進一步到「讓操作好用」。