今天要解的問題
在寫整理五張咖啡杯測表的差異時,我發現「總覽對照」那張表在桌機 960px 的內容欄裡只占了一半左右,右邊空一大片;手機上中文儲存格又不會斷行。而且為了讓它在手機 375px 不要橫向捲動,我還把儲存格用 <br> 切成很短的幾行,結果桌機上就更窄了。
但這不只是那一篇的事。把 kiwi-walk 上 50 篇有表格的文章、共 101 張表都量過一遍:
- 1280px 寬時,有 79 張表不到內容欄寬的九成。
- 375px 寬時,有 44 張表要橫向捲動。

技術背景
原因在 PaperMod 對所有 table 下的規則。reset.css 裡有兩條:
/* themes/PaperMod/assets/css/core/reset.css */
/* ... */
section,
table {
display: block;
}
/* ... */
table {
width: 100%;
border-collapse: collapse;
border-spacing: 0;
overflow-x: auto;
word-break: keep-all;
}
display: block:外框是 100% 寬,但裡面的表只撐到內容的寬度,不會拉滿。word-break: keep-all:中文字和字之間不能斷行。
另外 post-single.css 給每個儲存格一個最小寬度:
/* themes/PaperMod/assets/css/common/post-single.css */
.post-content table th,
.post-content table:not(.highlighttable, .highlight table, .gist .highlight) td {
min-width: 80px;
padding: 8px 5px;
/* ... */
}
加上左右各 5px 的 padding,5 欄就是 5 × (80 + 10) = 450px,比手機上 347px 的內容欄還寬,所以 600px 以下要把它歸零。
想法與取捨
一開始我想要的是這幾點:
- 桌機:文章表格拉滿內容欄寬。
- 手機:中文儲存格自然斷行,375px 不橫向捲動
- 改在
assets/css/extended/custom.css,不動主題 submodule。 - 不影響程式碼區塊的表格(
.highlight table、.highlighttable)和stack-tableshortcode。 - 改了之後,杯測那篇的
<br>可以考慮拿掉。
比較方式
先用 hugo 建好整個站,再用 Playwright 開那 50 篇文章,量每張表在 375px 和 1280px 的寬度。接著把候選的 CSS 直接注入建好的站,再量一次、截圖,拿真的頁面來比,而不是只畫 mockup。
塞不下的表
拉滿、斷行之後,手機上還是有表塞不進 347px。這時有三個做法:
- A:純 CSS,其中 4 張表改用
stack-table,不留任何橫捲。 - B:每張表外包可橫捲的框,不改文章,12 張表在手機上照舊橫捲。
- C:A 再加可橫捲的框當保險。
Claude 建議 A,我選了 B。
所以代價是:有 12 張表在手機上還是要在框內捲,「手機上不能橫向捲動」這條規則也多了一個例外。
杯測表的 <br>
Claude 原本建議保留,理由是那張表一格裝了兩個欄位,<br> 是在分欄位。
我選了這次一起改寫那張表,改成「6.00–9.75(0.25 一格)/無,直接加總」這種寫法,維持三欄。
實作
每張表包一層框
新增 layouts/_default/_markup/render-table.html:
{{/* ... */}}
<div class="table-wrap">
<table
{{- range $k, $v := .Attributes }}
{{- if $v }}
{{- printf " %s=%q" $k $v | safeHTMLAttr }}
{{- end }}
{{- end }}>
{{/* ... */}}
<tbody>
{{- range .TBody }}
<tr>
{{- range . }}
<td
{{- with .Alignment }}
{{- printf " style=%q" (printf "text-align: %s" .) | safeHTMLAttr }}
{{- end -}}
>{{- .Text -}}</td>
{{- end }}
</tr>
{{- end }}
</tbody>
</table>
</div>
{{- /**/ -}}
裡面照 Hugo table render hook 的範本輸出屬性、表頭、表身和每格的對齊,所以每張 Markdown 表外面都多了一層 <div class="table-wrap">。
覆寫表格規則
assets/css/extended/custom.css 檔尾加一段:
/* ... */
.post-content .table-wrap {
overflow-x: auto;
margin-bottom: var(--content-gap);
}
.post-content table:not(.highlighttable, .highlight table, .gist .highlight) {
display: table;
width: 100%;
word-break: normal;
overflow-wrap: break-word;
}
.post-content .table-wrap > table {
margin-bottom: 0;
}
@media (max-width: 600px) {
/* PaperMod's 80px cell minimum alone makes 4+ columns wider than 375px. */
.post-content table:not(.highlighttable, .highlight table, .gist .highlight) :is(th, td) {
min-width: 0;
}
}
每條對應 PaperMod 的一條規則:
display: table; width: 100%:取代display: block,表格拉滿欄寬。word-break: normal:取代keep-all,中文可以斷行;overflow-wrap: break-word讓真的放不下的字才斷開。- 600px 以下
min-width: 0:拿掉 80px 的儲存格下限。 .table-wrap的overflow-x: auto:還是塞不下的表,只在框內捲。
:not() 沿用 PaperMod 同一組排除,程式碼區塊的表照舊。
stack-table 的選擇器
同一個檔案裡,stack-table 手機版那條也加上同一組 :not(),原因寫在下面踩到的坑:
- .post-content .stack-table table {
+ .post-content .stack-table table:not(.highlighttable, .highlight table, .gist .highlight) {
杯測表
「總覽對照」的 <br> 換成括號和全形斜線,例如:
-| A. SCA 2004 | 6.00–9.75<br>(0.25 一格)<br>無,直接加總 | 100<br>80 |
+| A. SCA 2004 | 6.00–9.75(0.25 一格)/無,直接加總 | 100/80 |
最後在專案的寫作規則裡記下:文章表格是 <pre> 之外,第二個允許在框內橫捲的元件,新文章還是盡量讓表在 375px 塞得下。
踩到的坑
只改 word-break
只把 word-break 改成 normal,手機的捲動幾乎都消失(44 → 1)。但桌機的 79 張窄表一張都沒變,因為 display: block 還在。
anywhere 斷字
把 overflow-wrap: anywhere 套在所有儲存格,一張都不捲了,但連放得下的英文字也被從中間切開,例如 Supabas/e、Playwrig/ht、Assista/nt、14.9/4k。
anywhere 會把儲存格的最小寬度算成一個字,表格自動排版就把欄擠窄。改成 break-word 就不會。
code 要不要 anywhere
拿掉 code 的 anywhere,會多 5 張表撐破整頁(長的指令、路徑名稱)。但在可橫捲的框裡保留它,塞不下的表會先把程式碼欄擠成 1~2 個字寬(Heptabase 那張就是這樣)。
所以最後不給 code 設 anywhere,交給框去捲。
選擇器權重
新規則 .post-content table:not(.highlighttable, .highlight table, .gist .highlight) 的權重是 0,3,1(:not() 取裡面最重的 .gist .highlight),會蓋掉 stack-table 手機版的 display: block(0,2,1),About 的演講表就不堆疊了。
把 stack-table 那條也加上同一組 :not(),變成 0,4,1,演講表在手機上就又是一列一塊。
markdownify 的表
markdownify 也會走 table render hook,所以系列頁分組說明裡的表也被包了 .table-wrap。但那層 div 在 .post-content 外面,沒有任何樣式,量過寬高都和改前一樣。
小結
現在桌機上每張文章表格都拉滿欄寬,手機上中文會斷行,塞不下的 12 張只在自己的框裡捲,整頁不會捲。
| 量測(50 篇、101 張表) | 改前 | 改後 |
|---|---|---|
| 1280px 表寬不到欄寬 90% | 79 | 0 |
| 375px 表在框內橫捲 | 44 | 12 |
| 375px 整頁橫捲 | 0 | 0 |
最窄的表改前只有 240px(欄寬 960px);改後在 375px 最寬的那張(Heptabase「8.3 card」)撐到 765px,仍在框內捲。