自由接案者、ruby工程師、水肺潛水員、業餘羽球、二胡、鋼琴愛好者。喜歡貓、狗。

設計規範

這一頁是活的規範,不是截圖。所有色塊、字級、間距都直接用 var()tokens.css 裡的值,右側的數字也是瀏覽器解析後的實際結果 —— 改了 token,這一頁就跟著變。

00

最常被問的幾個

body 的底色、字色、字體、字級、行高、字距,以及連結的顏色與 hover —— 全部都是變數,app.css 裡的 bodya 規則沒有任何寫死的值。這套系統的連結不換色:hover 時只有底線由淺灰轉成墨色,因為單色系統裡線就是唯一的訊號。

assets/tokens.css
--surface-page
body 的背景色
--text-body
body 的文字色
--font-serif
body 的字體
墨白 Ink and Paper
--fs-root
html 的字級 —— 整站縮放的總開關
html { font-size }
--fs-400
body 的字級(1rem)
內文 18px
--lh-prose
body 的行高
中文方塊字沒有明顯的升降部,行高不夠時視線回到行首容易跳行。
--ls-cjk
body 的字距
墨白 Ink and Paper 2026
--text-link
連結文字色
--text-link-hover
連結 hover 文字色(刻意相同)
--text-link-rule
連結底線色
--text-link-rule-hover
連結底線色 hover
--link-rule-width
底線粗細
text-decoration-thickness
--link-rule-offset
底線與文字的距離
text-underline-offset
--link-rule-offset-title
大字標題用的較近距離
卡片與索引列的標題
html{font-size:var(--fs-root)}
body{background:var(--surface-page);
     color:var(--text-body);
     font-family:var(--font-serif);
     font-size:var(--fs-400);
     line-height:var(--lh-prose);
     letter-spacing:var(--ls-cjk)}
a{color:var(--text-link);
  text-decoration-color:var(--text-link-rule);
  text-decoration-thickness:var(--link-rule-width);
  text-underline-offset:var(--link-rule-offset)}
a:hover{color:var(--text-link-hover);
        text-decoration-color:var(--text-link-rule-hover)}
01

色階:紙與墨

整套系統只有一組中性色階。紙是米白(暖但不泛黃),墨是暖灰階,最深的一階收在冷中性的 #18181B —— 這一點小小的張力讓整體不落入懷舊感。元件永遠不直接用色階,只用下面的語意別名。

assets/tokens.css · 色彩
paper-000
paper-050
paper-100
paper-200
paper-300
ink-100
ink-200
ink-300
ink-400
ink-500
ink-600
ink-700
ink-800
ink-900
02

印刷第二色

四個色相,飽和度刻意壓到最低,在米白紙上看起來像「印刷的第二色」而不是介面警示燈。只給語意狀態用 —— 不能當品牌色、不能進導覽、不能上按鈕。

assets/tokens.css · 色彩
sage-050
sage-200
sage-600
ochre-050
ochre-200
ochre-600
rust-050
rust-200
rust-600
slate-050
slate-200
slate-600
03

表面、文字、線

第二層:語意別名。元件只碰這一層,所以換色不必改任何元件。表面只有三階(紙、稍亮的紙、下沉的紙);文字四級全靠明度差,沒有色相變化;線是這套系統的主要結構工具 —— 沒有卡片外框、沒有陰影,層級都靠它。命名分工:--border-* 是結構分隔線,--text-link-rule--link-rule-* 裡的 rule 指的是連結底下的裝飾線,兩者不同。

assets/tokens.css · 色彩
表面 surface
--surface-page
--surface-card
--surface-raised
--surface-sunken
--surface-inverse
--surface-hover
--surface-active
文字 text
--text-title
--text-body
--text-muted
--text-inverse
--text-on-accent
--text-link
--text-link-rule
線 border
--border-hairline
--border-subtle
--border-default
--border-strong
04

強調與語意狀態

沒有彩色強調色 —— 強調就是墨本身。需要強調時用大一級的字、粗一階的重量,或一條線。語意狀態則是三件成套(文字色、淡底、框線),永遠一起用。

assets/tokens.css · 色彩
強調 accent
--accent-primary
--accent-primary-hover
--accent-primary-active
--accent-primary-tint
語意狀態 semantic
--success-fg
--success-bg
--success-border
--warning-fg
--warning-bg
--warning-border
--danger-fg
--danger-bg
--danger-border
--info-fg
--info-bg
--info-border
實際樣子
已發佈 草稿 已刪除 置頂 附件 4
05

報頭與頁尾

第三層:角色別名。報頭與頁尾各有獨立的一組,換整站骨架配色只改這兩組,不會動到內容區。Toast 也自己一組 —— 它畫在會翻色的反色面板上,不能借用頁面主題的語意色。

assets/tokens.css · 色彩
報頭 header
--header-bg
--header-fg
--header-muted
--header-link
--header-link-hover
--header-link-active
--header-border
--header-icon
--header-icon-hover
頁尾 footer
--footer-bg
--footer-fg
--footer-muted
--footer-link
--footer-link-hover
--footer-border
反色面板 toast
--toast-bg
--toast-fg
--toast-muted
--toast-mark-success
--toast-mark-danger
其他
--focus-ring
--selection-bg
--selection-fg
--mark-bg
--mark-fg
--tag-fg
--tag-border
--tag-bg-hover
--tag-fg-hover
--code-bg
--code-fg
--code-border
--skeleton-bg
06

夜間模式

[data-theme="dark"] 只覆寫語意別名,色階與元件都不動。單色系統的好處:夜間版不需要重新選色,只要把明度翻過來。按右上角的月亮鈕,這一頁的所有數值會即時跟著變 —— 那就是這套 token 架構的證明。

assets/tokens.css · 色彩
試試看

切換夜間模式後回到上面幾節,右側的數值會全部換成深色版的值。這一頁沒有寫死任何一個 hex。

07

字體家族

標題與內文都是宋體。黑體只負責 meta、圖說、小標、按鈕與表單;等寬負責程式碼、token 名稱與索引列日期。Source 系列與思源同源,拉丁與漢字骨架一致,混排不打架。

assets/tokens.css · 字體
--font-serif 標題與內文都用宋體 The quick brown fox
--font-sans 介面與 meta 用黑體 The quick brown fox
--font-mono 等寬 --space-unit: 4px
08

字級階梯

--fs-root(18px)為基準的 rem 階梯。內文是 --fs-400,階梯開到 --fs-1200(90px)是因為雜誌頭條需要一個真的很大的標題。改 --fs-root 就能整站等比縮放。

assets/tokens.css · 字體
Aa100
Aa200
Aa300
Aa400
Aa500
Aa600
Aa700
Aa800
Aa900
Aa1000
Aa1100
Aa1200
--fs-1100文章大標
--fs-1000頭條標題
--fs-800章節標題
--fs-700卡片標題
--fs-500導言
--fs-400內文
--fs-300小字
--fs-100小標
h1–h6 的預設字級

標籤只是掉回瀏覽器預設值的保險 —— 沒有這組映射,裸 h6 會比內文還小、四個層級會落在階梯之外。實際版面請用角色 class(.page-title / .card__title / .prose h2),因為這套系統的字級由角色決定,不由標籤深度決定.card__title 標記是 h3 卻是 27px,.prose h3 是 20px,.page-title 標記是 h1 卻是 54px。所以刻意不設 --h1-size 這類以標籤命名的變數 —— 那會宣告一條全站沒人遵守的規則。

h1
→ --fs-900
h1 標題樣本
h2
→ --fs-800
h2 標題樣本
h3
→ --fs-700
h3 標題樣本
h4
→ --fs-600
h4 標題樣本
h5
→ --fs-500
h5 標題樣本
h6
→ --fs-400
h6 標題樣本

字重、行高、字距三項共用一組--fw-semibold / --lh-snug / --ls-tight),只有 h1 與 h2 因為字大而改用 --lh-tight--ls-tighter。手機版不另外覆寫 —— rem 階梯已經隨 --fs-root(18→17px)等比縮小,六級在 375px 下仍然各自分明(39.7 / 32.1 / 25.5 / 21.7 / 18.9 / 17px)。

09

行高與字距

內文行高 1.95 —— 中文方塊字沒有明顯升降部,宋體筆畫又比黑體細,1.6 會跳行。字距給中文正文一點正值(--ls-cjk),大標則收緊。全大寫的拉丁小標用 --ls-caps 放鬆。

assets/tokens.css · 字體
行高 line-height
--lh-poster 中文方塊字沒有明顯的升降部,行與行之間如果太密,視線回到行首時容易跳行。
--lh-tight 中文方塊字沒有明顯的升降部,行與行之間如果太密,視線回到行首時容易跳行。
--lh-snug 中文方塊字沒有明顯的升降部,行與行之間如果太密,視線回到行首時容易跳行。
--lh-normal 中文方塊字沒有明顯的升降部,行與行之間如果太密,視線回到行首時容易跳行。
--lh-prose 中文方塊字沒有明顯的升降部,行與行之間如果太密,視線回到行首時容易跳行。
字距 letter-spacing
--ls-poster 墨白 Ink and Paper 2026
--ls-tighter 墨白 Ink and Paper 2026
--ls-tight 墨白 Ink and Paper 2026
--ls-normal 墨白 Ink and Paper 2026
--ls-cjk 墨白 Ink and Paper 2026
--ls-wide 墨白 Ink and Paper 2026
--ls-caps 墨白 Ink and Paper 2026
字重 font-weight
--fw-regular 墨白 Ink and Paper
--fw-medium 墨白 Ink and Paper
--fw-semibold 墨白 Ink and Paper
--fw-bold 墨白 Ink and Paper
10

間距

全部由 --space-unit(4px)推導。改那一個值,整站鬆緊同步。段距用容器的 gap 而不是 margin-bottom —— 刪掉任何一段都不會留下多餘空白。

assets/tokens.css · 間距
--space-unit ·
--space-1 ·
--space-2 ·
--space-3 ·
--space-4 ·
--space-5 ·
--space-6 ·
--space-8 ·
--space-10 ·
--space-12 ·
--space-16 ·
--space-20 ·
--space-24 ·
--space-32 ·
--space-40 ·
11

版面寬度

三種寬度撐起整站:內文閱讀欄 --measure(約每行 30–34 個漢字)、文章欄 --content-max、列表 --wide-max;滿版影像可到 --bleed-max。下圖的每一條都是 app.js 依實際 token 值算出的比例(以 --bleed-max 為 100%),沒有寫死任何百分比 —— 改了 token,圖與右側數值會一起變。

assets/tokens.css · 版面
頁面寬度 · 相對比例
--bleed-max
滿版影像的上限
--wide-max
列表與報頭的最大寬
--content-max
文章欄寬
--measure
內文行長 · 約每行 30–34 個漢字
--sidebar-width
分類側欄
實心的兩條是最常用的:--wide-max(列表與報頭)與 --measure(內文行長)。
其他版面值
--gutter
--gutter-lg
--header-height
--masthead-height
--section-gap
--block-gap
--paragraph-gap
--grid-gap
--card-padding
--control-height
--control-height-sm
--control-height-lg
12

圓角與線寬

圓角全部是零。書與雜誌沒有圓角,只有頭像是圓的。想要柔一階就把 --radius-sm/md/lg 改成 2/4/6px,元件全走語意別名,不必逐一改。線寬四階:1px 細線、2px 章節、3px 報頭、4px 引言。

assets/tokens.css · 圓角
圓角 radius
--radius-0
--radius-sm
--radius-md
--radius-lg
--radius-control
--radius-card
--radius-image
--radius-tag
--radius-pill
--radius-circle
線寬 border-width
--border-width
--border-width-thick
--border-width-rule
--border-width-accent
--focus-ring-width
13

陰影

幾乎不用。層級來自線與留白,不是浮起來的盒子 —— 只有真正離開紙面的東西才有陰影。顏色抽成 --shadow-rgb 加三段 alpha,改一組就能整站調整。深色主題不是把同一個陰影加深:深底加深陰影沒有對比(實測只有 1.1:1),所以夜間改用純黑加重,再疊一道 --shadow-ring 亮邊 —— 那道 1px 邊才是深底上真正撐出層級的東西。切夜間看下面兩組方塊就知道差別。

assets/tokens.css · 陰影
組成的變數
--shadow-rgb
陰影的顏色(淺色暖墨、夜間純黑)
--shadow-alpha-sm
小陰影的濃度
--shadow-alpha-md
中陰影的濃度
--shadow-alpha-lg
大陰影的濃度
--shadow-ring
夜間才出現的 1px 亮邊(單獨看)
--lightbox-bg
圖庫燈箱底色
--lightbox-rule
燈箱工具列的分隔線
四個層級 · 括號內是目前實際用它的元件
--shadow-none
卡片、文章列表、所有內容區 —— 預設就是沒有陰影
--shadow-sm
目前沒有使用者,保留給未來的細微浮起
--shadow-md
桌機 header 的子選單下拉
--shadow-lg
彈窗(搜尋)與 Toast
14

動態

更少、更短。hover 只換線色或明度;沒有位移、沒有縮放、沒有彈跳。按下只降透明度到 --press-opacity,封面 hover 降到 --image-hover-opacity(不放大)。prefers-reduced-motion 時動畫全部歸零。

assets/tokens.css · 動態
時長 · 示範放慢 9 倍才看得見
--dur-fast
hover:只換色
--dur-base
展開/收起
--dur-slow
彈窗、燈箱
Easing
--ease-standard
全站唯一的曲線
透明度
--press-opacity 按下的按鈕
--image-hover-opacity hover 的封面
實際互動 · 移上去看
15

圖示

一律 Font Awesome 6 Free(fa-solid 介面、fa-brands 社群)。顏色永遠繼承 currentColor,社群圖示不用各平台品牌色 —— 那會毀掉單色系統。不手繪 SVG、不用 emoji。

assets/tokens.css · 圖示
--icon-size-xs
--icon-size-sm
--icon-size-md
--icon-size-lg
--icon-size-xl
--icon-gap
16

用法規則

這些不是建議,是這套系統之所以長這樣的原因。破壞任何一條,它就不再是墨白。

這樣做 元件只用語意層與角色層--text-body--header-link 強調用字級、字重、線 層級用1px 細線與留白 中文強調用加粗著重號或換黑體 沒有照片時顯示誠實的佔位框
不這樣做 元件直接寫 --ink-900 或 hex(夜間會壞) 加一個彩色強調色 卡片加外框、底色或陰影 中文用斜體(印刷史上不存在) 用生成圖或圖庫假圖填空
換膚的順序

先改 --accent-primary--header-* / --footer-*,再看 --font-serif--fs-root,最後才動 --space-unit--radius-*。每改一組就回這一頁看一次。

改了會影響全站的三個值

--space-unit(所有間距)、--fs-root(所有字級)、--radius-sm/md/lg(所有圓角)。這三個是槓桿最大的,也最容易一改就整站走樣 —— 改完請逐頁看過。