返回總覽

本頁排版參數

字級比例

Perfect Fourth (1.333)

內文字級

16px (base)

內文行高

1.75 (body)

內文字距

0em (default)

標題行高

1.4 (heading)

標題字距

0em (default)

字型

Noto Sans TC

行長控制

max 40rem (~40字/行)

分類標籤 — text-sm / font-medium / text-primary

設計觀點

文章標題 h1 — text-4xl (38px) / font-bold / clamp() 響應式

為什麼設計系統是產品成功的基石

文章 Meta — text-sm / text-text-tertiary
2025 年 6 月 15 日閱讀時間約 12 分鐘作者:設計團隊
引言段落 — text-lg (18px) / text-text-secondary / 比內文大一級

在現代產品開發中,設計系統已經從「加分項目」變成了「必需品」。一套好的設計系統不僅能加速開發流程,更能確保使用者在不同平台上獲得一致的體驗。本文將探討設計系統的核心價值,以及如何從零開始建立屬於你的設計語言。

TL;DR — bg-bg-secondary / rounded-md / 摘要重點

TL;DR

設計系統是產品的基礎建設投資。它統一設計語言、加速開發、確保一致性。對繁體中文產品而言,更需要關注 CJK 排版細節——行高 1.75、最小字級 12px、Perfect Fourth 字級比例。
段落大標題 h2 — text-3xl (28px) / font-bold / clamp() 響應式

什麼是設計系統?

內文段落 — text-base (16px) / text-text-primary / line-height 1.75

設計系統(Design System)是一套完整的設計標準集合,包含了可重複使用的元件設計 Token、以及使用指南。它是設計師與開發者之間的共同語言,確保團隊中的每個人都在同一個基礎上工作。

不同於 UI Kit 或元件庫,設計系統更加全面。它不僅定義了視覺元素的外觀,還規範了它們的行為、使用情境與無障礙性要求。從字型大小到按鈕的互動狀態,每一個細節都有明確的規範。

引用區塊 Blockquote — bg-bg-secondary / rounded-xl / 底色色塊

「設計系統不是一個專案,而是一個產品。它需要持續維護、迭代與更新,才能真正發揮價值。」

— Brad Frost, Atomic Design 作者
段落大標題 h2 — text-3xl (28px) / font-bold

設計系統的核心組成

一個成熟的設計系統通常包含以下幾個層面,從最基礎的 Token 到高階的頁面模板:

有序列表 ol — list-decimal / text-base / space-y-3
  1. 設計 Token — 色彩、字型、間距、圓角等最基礎的設計決策,通常以變數的形式存在。
  2. 基礎元件 — 按鈕、輸入框、標籤等最小的 UI 構建塊,每個元件都有明確的 API 與使用規範。
  3. 複合元件 — 由多個基礎元件組合而成的模組,例如表單、卡片、導覽列等。
  4. 頁面模板 — 定義了常見頁面的佈局結構,提供一致的使用者體驗框架。
段落子標題 h3 — text-2xl (24px) / font-semibold (600) / clamp() 響應式

CJK 排版的挑戰

對於繁體中文產品來說,設計系統需要額外關注排版(Typography)的細節。CJK 字元的結構與 Latin 字母截然不同,這帶來了幾個獨特的挑戰:

無序列表 ul — list-disc / text-base / space-y-3
  • CJK 字元每個字寬度相同(等寬字元),而 Latin 字母則是比例字元,兩者混合排列時需要特別處理間距
  • 繁體中文筆畫較多,在小尺寸下容易糊成一團,因此最小字級不宜低於 12px
  • 行高需要比英文更大——繁體中文建議使用 1.75 而非英文常用的 1.5
  • 標點符號的位置與間距需要符合中文排版慣例,例如全形標點不應出現在行首
資訊提示卡 — bg-primary/5 / border-primary/20 / 用於重要補充
i

關於 Perfect Fourth 比例

Brickverse 的字級系統採用 Perfect Fourth (1.333) 比例,相較於常見的 Major Third (1.250), 在中文方塊字環境下能提供更強烈的層級對比。基準字級 16px 乘以 1.333 得到 21px、28px、38px 等字級, 每一級之間的跳躍在視覺上都能清楚感知。

表格 Table — text-sm / 用於結構化資訊比較

字級比例對照表

以下為 Brickverse 設計系統中各個字級 Token 的具體數值與對應的使用場景:

Token大小使用場景字重
text-4xl38px頁面主標題 (h1)Bold 700
text-3xl28px段落大標題 (h2)Bold 700
text-2xl24px段落子標題 (h3)SemiBold 600
text-xl21px小標題 (h4)Medium 500
text-lg18px引言段落、h5Medium 500
text-base16px內文Regular 400
text-sm14px輔助文字、標籤Regular/Medium
text-xs12px圖說、最小文字Regular 400
段落大標題 h2 — text-3xl (28px) / font-bold

建立設計系統的步驟

從我們在 Brickverse 的實踐經驗出發,我們將建立設計系統的過程拆解為五個階段。每個階段都有明確的目標與交付物,確保團隊能夠循序漸進地推動這項工作。

小標題 h4 — text-xl (21px) / font-medium (500)

第一階段:設計稽核

在開始建立設計系統之前,首先需要對現有產品進行全面的設計稽核。這個步驟的目的是盤點目前已經存在的設計元素,找出不一致的地方,並確定優先需要標準化的項目。

巢狀列表 — ul 內含 ul / 用於多層次資訊
  • 視覺元素盤點
    • 色彩:記錄所有使用中的色彩值,找出相似但不同的色碼
    • 字型:統計不同頁面使用的字級、字重組合
    • 間距:檢查 padding、margin 是否有一致的規律
  • 元件盤點
    • 按鈕:找出所有不同樣式的按鈕,歸納出核心變體
    • 表單控制項:輸入框、下拉選單、勾選框等
    • 導覽元件:頂部導覽、側邊欄、麵包屑等
  • 互動模式盤點
    • 動態效果:hover、focus、active 狀態的處理方式
    • 過渡動畫:元素出現、消失、狀態切換的動畫時長與曲線
小標題 h4 — text-xl (21px) / font-medium (500)

第二階段:建立 Token 系統

Token 是設計系統的原子級基礎。它們是以變數形式存在的設計決策,涵蓋色彩、字型、間距、圓角、陰影等面向。Brickverse 使用 TypeScript 定義 Token,搭配 Tailwind CSS v4 的 @theme inline 實現 CSS 自訂屬性的自動生成。

程式碼區塊 CodeBlock — font-mono / text-sm / bg-bg-tertiary
TypeScript — Token 定義範例
// src/tokens/typography.ts
export const fontSizes = {
  xs:    { value: '0.75rem',    px: 12 },
  sm:    { value: '0.875rem',   px: 14 },
  base:  { value: '1rem',       px: 16 },
  lg:    { value: '1.125rem',   px: 18 },
  xl:    { value: '1.3125rem',  px: 21 },
  '2xl': { value: '1.5rem',     px: 24 },
  '3xl': { value: '1.75rem',    px: 28 },
  '4xl': { value: '2.375rem',   px: 38 },
} as const;

第三階段:元件開發

基於 Token 系統,開始開發最常用的基礎元件。每個元件都應該具備完整的變體(variant)、尺寸(size)、狀態(state)定義,並附帶使用文件。

警告提示卡 — bg-accent/10 / border-accent / 用於注意事項
!

注意:中文字重的限制

在 Windows 10 以後的系統上,字重低於 300 會出現渲染模糊的問題。因此 Brickverse 設計系統建議最低字重為 Regular (400), Light (300) 僅在特殊裝飾性場景中使用。這是中文字型特有的考量——中文筆畫密度高,過細的字重會嚴重影響可讀性。

第四階段:文件與治理

設計系統的長期成功取決於完善的文件和治理機制。文件不只是給設計師看的——開發者、PM、QA 都需要理解設計決策背後的邏輯。

定義列表樣式 — 用於術語解釋 / key-value 形式
Design Token
設計系統中最小的、不可再分割的設計決策單位,例如一個色碼值 #0184ff 或一個間距值 16px
Fluid Typography
使用 CSS clamp() 函數讓字級在不同螢幕寬度之間平滑縮放,避免在斷點處產生突兀的跳變。
Vertical Rhythm
垂直韻律——頁面上所有元素的間距都是基本行高的倍數,營造出一致、和諧的排版節奏。

第五階段:持續迭代

設計系統不是一個「做完就結束」的專案,而是一個持續演進的產品。團隊需要建立定期回顧的機制,根據實際使用反饋不斷調整和優化。

步驟列表 — 帶數字圓圈 / 用於流程說明
1

收集回饋

定期向使用設計系統的設計師和開發者收集意見,了解哪些元件好用、哪些需要改進。

2

分析數據

追蹤元件的使用頻率和覆蓋率,找出最常被客製化覆寫的元件——這通常意味著 API 設計不夠靈活。

3

版本規劃

使用語意化版本號(SemVer),明確區分 patch、minor、major 更新,讓使用者能安全地升級。

4

發布與溝通

每次更新都附帶完整的 changelog,並在團隊內部進行溝通,確保所有人了解變更內容。

實際案例:Brickverse 的排版決策

以下是我們在建立 Brickverse 字型系統時做出的幾個關鍵決策,以及背後的思考過程。這些經驗對於任何需要處理中文排版的團隊都有參考價值。

為什麼選擇 Noto Sans TC?

我們在字型選擇上評估了多個方案,最終選定 Noto Sans TC 作為主要字型。決策因素包括:

對比卡片 — grid 佈局 / 用於方案比較

Noto Sans TC 的優勢

  • - 免費開源,無授權費用問題
  • - Google Fonts 直接載入,CDN 快速
  • - 覆蓋完整的繁體中文字集
  • - 提供 7 種字重 (100-900)
  • - 內建中英文字距微調

需要注意的地方

  • - 中文字體檔案較大(需做子集化)
  • - 某些罕用字可能缺字
  • - 極小字級 (10px) 下渲染略粗
  • - 與其他 CJK 字體混排需校準

響應式字級的實作

我們使用 CSS clamp() 函數實現 Fluid Typography。以 h1 為例,它在 640px 的手機螢幕上渲染為 28px, 隨著螢幕增大平滑縮放,最終在 1280px 以上的桌面螢幕上達到 38px。中間任何寬度都會自動插值,不需要手動設定斷點。

程式碼區塊 — Fluid Typography CSS 範例
CSS — Fluid Typography
/* globals.css — h1 的 fluid typography */
h1 {
  font-weight: 700;
  letter-spacing: 0em;
  line-height: 1.4;
  font-size: clamp(1.75rem, 1.25rem + 1.25vw, 2.375rem);
  /*         最小值28px  ↑ 線性縮放公式    最大值38px */
}

/* body 不做 fluid,保持固定 16px */
body {
  font-size: 1rem;
  line-height: 1.75;
  letter-spacing: 0em;
}

程式碼與行內標記

在技術文件中,經常需要在文字中穿插程式碼片段。行內程式碼使用 <code> 標籤,會自動套用 font-mono 字型、text-sm 字級和淺灰背景。例如:使用 var(--text-4xl) 來引用 38px 的字級變數, 或者透過 className="text-4xl font-bold" 來直接套用 Tailwind 的類別。

圖片區塊 figure — 含 figcaption 圖說 / text-sm / text-text-tertiary
圖片範例區域 — 1200 x 630
圖 1:Brickverse Design System 的字級量表視覺化。從 12px (xs) 到 67px (6xl), Perfect Fourth 比例確保每一級之間都有足夠的視覺差異。
數據亮點 — grid 佈局 / 用於展示關鍵數字

設計系統的投資報酬率

根據多項業界研究,導入設計系統後的產品團隊在效率和品質上都有顯著的提升:

47%

開發速度提升

33%

設計一致性改善

60%

元件重複使用率

25%

維護成本降低

最小標題 h5 — text-lg (18px) / font-medium (500) / 與 body 靠字重區分
關於數據的說明

上述數據來自 Forrester Research 對大型企業設計系統的調查報告。實際效果因團隊規模、產品複雜度和導入深度而異。 小型團隊的投資報酬期可能更短,但也需要根據實際情境評估是否適合建立完整的設計系統。

「好的排版是隱形的——讀者應該專注於內容本身,而非字型的存在。當你注意到排版的時候,通常代表它出了問題。」

— Oliver Reichenstein, iA Writer 創辦人
段落大標題 h2 — text-3xl (28px) / font-bold

Markdown 渲染情境案例

在 CJK(中日韓)排版環境下,Markdown 渲染引擎(如 marked.js)會遇到一些 Latin 語系不會出現的 edge case。以下記錄了我們在 Brickverse Blog 實際遇到的情境與解法,作為設計系統的排版筆記。

情境 1 — 粗體後緊接 CJK 字元

情境 1:粗體後緊接中文字元

CommonMark 規範要求右側 flanking delimiter(**)後面不能緊接字母或 CJK 字元,否則不被視為粗體結束標記。這導致以下 Markdown 在預設 marked.js 中無法正確渲染:

Markdown — 粗體後緊接中文(渲染失敗)
**CDP 是 Chrome DevTools Protocol 的縮寫。**如果你用過 Chrome 開發者工具...

// marked.js 預設輸出:
// <p>**CDP 是 Chrome DevTools Protocol 的縮寫。**如果你用過...</p>
// ↑ 星號原封不動輸出,沒有轉成 <strong>

解法:自訂 marked.js 的 emStrong tokenizer,放寬右側 delimiter 的規則,讓 **text** 後面即使緊接 CJK 字元也能正確關閉。

TypeScript — CJK 友好的 emStrong tokenizer
import { marked, type TokenizerObject } from 'marked';

const tokenizer: TokenizerObject = {
  emStrong(src: string) {
    // Bold: 更寬鬆的匹配,不要求 ** 後面是空格
    const boldMatch = src.match(/^\*\*([\s\S]+?)\*\*/);
    if (boldMatch) {
      return {
        type: 'strong',
        raw: boldMatch[0],
        text: boldMatch[1],
        tokens: this.lexer.inlineTokens(boldMatch[1]),
      };
    }
    // Italic: 同理
    const emMatch = src.match(/^\*([\s\S]+?)\*/);
    if (emMatch) {
      return {
        type: 'em',
        raw: emMatch[0],
        text: emMatch[1],
        tokens: this.lexer.inlineTokens(emMatch[1]),
      };
    }
    return false;
  },
};

marked.use({ tokenizer });
情境 2 — Markdown 中嵌入 inline HTML(已淘汰)

⚠ 已淘汰 — Legacy HTML 轉換層已於 2026-02-13 完全移除,資料庫所有文章皆為 Markdown 格式,不再需要 htmlToMarkdown() 函式,此情境僅作為歷史參考。

情境 2:Markdown 中嵌入 Font Awesome icon

文章中使用 <i class="fas fa-circle-check"></i> 嵌入 Font Awesome icon 時,如果有一個 HTML→Markdown 的轉換函式,它可能會把 <i> 標籤當成「斜體」轉換,導致空的 <i> 變成 **(兩個空斜體星號)。

問題:<i> 標籤被誤判為斜體
// 原始 Markdown:
✓ 完成項目 <i class="fas fa-circle-check"></i>

// htmlToMarkdown() 處理後:
✓ 完成項目 **
// ↑ <i></i> 被 regex 轉成 *空字串*,變成兩個星號

解法:在轉換前用 placeholder 保護 Font Awesome 的 <i> 標籤,轉換完成後再還原。

TypeScript — 保護 FA icon 的 htmlToMarkdown
// 先保護 FA <i> 標籤
const faIcons: string[] = [];
markdown = markdown.replace(
  /<i\s+[^>]*class="[^"]*fa-[^"]*"[^>]*><\/i>/gi,
  (match) => {
    faIcons.push(match);
    return `%%FA_ICON_${faIcons.length - 1}%%`;
  }
);

// 轉換普通 <i> 為斜體
markdown = markdown.replace(/<i[^>]*>(.*?)<\/i>/gi, '*$1*');

// 還原 FA icon
markdown = markdown.replace(/%%FA_ICON_(\d+)%%/g, (_, idx) => {
  return faIcons[parseInt(idx, 10)];
});
情境 3 — 內容格式自動偵測(已淘汰)

⚠ 已淘汰 — Legacy HTML 轉換層已於 2026-02-13 完全移除。資料庫 13 篇文章經查全部為 Markdown 格式(0 篇 HTML),格式偵測邏輯不再需要,此情境僅作為歷史參考。

情境 3:Markdown vs Legacy HTML 自動偵測

當系統同時存在舊版(Quill 編輯器產出的 HTML)和新版(Markdown)文章時,不能對所有內容都執行 HTML→Markdown 轉換——否則已經是 Markdown 的文章會被破壞。需要一個偵測函式判斷內容格式。

TypeScript — 智慧內容格式偵測
function detectContentFormat(content: string): 'markdown' | 'html' {
  if (!content) return 'markdown';
  if (!/<[^>]+>/.test(content)) return 'markdown';

  // Markdown 特徵:## 標題、**粗體**、``` code fence、[link](url) 等
  const markdownSignals = [
    /^#{1,6}\s/m,        // # heading
    /\*\*[^*]+\*\*/,      // **bold**
    /```[\s\S]*?```/,  // code fence
    /\[.+?\]\(.+?\)/,    // [text](url)
    /^\s*[-*+]\s/m,      // - list item
  ];

  // HTML 結構特徵:<p>、<div>、<strong> 等
  const htmlSignals = [
    /<p[^>]*>/i, /<div[^>]*>/i, /<h[1-6][^>]*>/i,
    /<strong[^>]*>/i, /<em[^>]*>/i,
  ];

  // 有任何 Markdown 語法 → 判定為 Markdown(即使含 inline HTML)
  for (const pattern of markdownSignals) {
    if (pattern.test(content)) return 'markdown';
  }
  for (const pattern of htmlSignals) {
    if (pattern.test(content)) return 'html';
  }
  return /^\s*</.test(content) ? 'html' : 'markdown';
}
i

關鍵原則:Markdown 優先

偵測邏輯優先檢查 Markdown 特徵。因為「Markdown 含 inline HTML」(如 Font Awesome icon)是合法的 Markdown, 不應被當成 Legacy HTML 處理。只有在完全沒有 Markdown 語法、且有 HTML 結構標籤時,才判定為 HTML。

情境 4 — DOMPurify 安全過濾配置

情境 4:DOMPurify 過濾掉 inline HTML

使用 dangerouslySetInnerHTML 渲染 Markdown 轉出的 HTML 時,必須用 DOMPurify 做安全過濾。但預設配置會移除 <i> 標籤的 class 屬性,導致 Font Awesome icon 失效。

TypeScript — DOMPurify 允許 FA icon
import DOMPurify from 'isomorphic-dompurify';

const rawHtml = marked.parse(content, { renderer }) as string;

// 必須明確允許 <i> 標籤和 class 屬性
const safeHtml = DOMPurify.sanitize(rawHtml, {
  ADD_TAGS: ['i'],
  ADD_ATTR: ['class', 'aria-hidden', 'role', 'style'],
});
情境總覽表 — 快速參照

CJK Markdown 渲染 Edge Case 總覽

情境症狀根因解法
**粗體**中文星號原封不動顯示CommonMark 右側 delimiter 規則自訂 emStrong tokenizer
FA <i> icon 已淘汰顯示 **htmlToMarkdown<i> 當斜體Legacy 層已移除
Markdown 含 HTML 已淘汰整篇內容被破壞htmlToMarkdown 誤判格式Legacy 層已移除
DOMPurify 過濾icon 消失預設移除 <i> 的 classADD_TAGS + ADD_ATTR
段落大標題 h2 — text-3xl (28px) / font-bold

結語

設計系統是一項長期投資。短期內它需要團隊投入時間與精力來建立和維護,但長期來看,它能大幅減少重複工作、提升產品品質、加速新功能的開發速度。對於任何認真對待使用者體驗的團隊來說,設計系統都是值得投入的基礎建設。

特別是對於繁體中文產品,排版的品質直接影響使用者對產品的信任感與專業度。從字型選擇、字級比例到行高行距,每一個看似微小的決定都在塑造整體的閱讀體驗。我們相信,花時間在這些基礎上是值得的。

次要段落 — text-base / text-text-secondary / 用於結尾補充

我們會持續在 Brickverse Design System 中加入更多元件與模板,為開發者提供更完整的工具鏈。如果你對我們的設計決策有任何想法或建議,歡迎與我們交流。

文章標籤 — text-xs / font-medium / 圓角膠囊
設計系統Typography中文排版CJKTailwind CSSDesign Token響應式設計
作者卡片 — 用於文章底部 / 頭像 + 簡介
B

Brickverse 設計團隊

我們是一群熱愛設計與開發的團隊,致力於打造最適合繁體中文環境的設計系統。 從 Token 到元件、從排版到動畫,我們用系統化的思維解決每一個設計問題。