Guide / 15 min

軟體工程師的設計原則

學習構建更好軟體的設計基礎。排版、色彩理論、間距、動畫,以及從Arc到Stripe的16個產品案例研究。

2026年2月更新

2026年2月更新: 新增兩個章節——互動模式(研究 Framer、Flighty、Halide、Warp、Bear、Craft 和 Superhuman 後歸納的8種範式)以及 AI 介面模式(引用優先設計、串流階段、來自 Perplexity 的錯誤透明度)。將網頁模式更新至2026年,涵蓋錨點定位、捲動驅動動畫及 @starting-style。更新無障礙章節以反映 WCAG 2.2 的 ISO 標準化。請參閱設計研究深入了解16款卓越產品。

多年來,我一邊打造軟體,一邊鑽研設計——從 Dieter Rams 等傳奇大師身上汲取原則,拆解 Linear、Stripe 和 Raycast 等產品的介面。這份指南將這些理解濃縮為一份全面的參考資源,正是我當初開始在意軟體外觀與體驗時,最希望擁有的那種。

設計不是裝飾,而是溝通。每一個像素都在傳達功能、層級與意義。業餘感與專業感之間的差距,在於是否理解這些原則並一致地加以運用。

本指南假設您已具備程式撰寫能力。它要教會您的是「看見」——理解為何有些介面讓人感到毫不費力,而其他介面卻令人混亂,更重要的是,學會如何打造前者。


目錄

第一部分:基礎理論

  1. Gestalt 心理學
  2. 字體排版
  3. 色彩理論
  4. 視覺層級
  5. 間距與韻律
  6. 動畫原則

第二部分:互動與 AI

  1. 互動模式
  2. AI 介面模式

第三部分:設計哲學

  1. Dieter Rams:十大原則

第四部分:實作

  1. 2026年網頁模式
  2. Design Tokens 系統
  3. 正確實作深色模式
  4. Figma 匯出工作流程

第五部分:參考資料

  1. 快速參考表
  2. 設計檢查清單
  3. 設計研究

Gestalt 心理學

「整體不同於各部分的總和。」— Kurt Koffka

Gestalt 心理學起源於1920年代的德國,用以解釋人類如何感知視覺資訊。大腦不會逐一辨識像素,而是將元素組織成有意義的模式。掌握這些原則,您就能掌控使用者感知介面的方式。

接近性

距離相近的元素會被視為一個群組。

這是 UI 設計中最強大的 Gestalt 原則。間距傳達關聯性的能力勝過任何其他視覺屬性。

WRONG (equal spacing = no grouping):
┌─────────────────┐
│ Label           │
│                 │
│ Input Field     │
│                 │
│ Label           │
│                 │
│ Input Field     │
└─────────────────┘

RIGHT (unequal spacing = clear groups):
┌─────────────────┐
│ Label           │
│ Input Field     │ ← Tight (4px) - related
│                 │
│                 │ ← Wide (24px) - separating groups
│ Label           │
│ Input Field     │ ← Tight (4px) - related
└─────────────────┘

CSS 實作:

.form-group {
  margin-bottom: 24px;  /* Between groups: wide */
}

.form-group label {
  margin-bottom: 4px;   /* Label to input: tight */
  display: block;
}

SwiftUI 實作:

VStack(alignment: .leading, spacing: 4) {  // Tight within group
    Text("Email")
        .font(.caption)
        .foregroundStyle(.secondary)
    TextField("[email protected]", text: $email)
        .textFieldStyle(.roundedBorder)
}
.padding(.bottom, 24)  // Wide between groups

相似性

具有相同視覺特徵的元素會被視為相關。

當元素看起來相同時,使用者會假設它們的功能也相同。這就是為什麼設計系統會使用一致的按鈕樣式、卡片處理方式和字體排版。

Example Navigation:
┌───────────────────────────────────┐
 [Dashboard] [Projects] [Settings]    Same style = same function
                                   
 ┌─────┐  ┌─────┐  ┌─────┐        
 Card   Card   Card             Same style = same content type
 └─────┘  └─────┘  └─────┘        
                                   
 [+ New Project]                      Different style = different function
└───────────────────────────────────┘

圖與地

內容應與背景清楚分離。

大腦需要區分「圖」(聚焦目標)與「地」(背景)。圖地關係不佳會造成視覺混亂。

技巧: - 對比(亮色圖在暗色地之上,或反之) - 陰影(將圖提升至地之上) - 邊框(界定圖的邊緣) - 模糊(模糊背景,銳化前景)

/* Strong figure-ground relationship */
.card {
  background: var(--color-surface);     /* Figure */
  border-radius: 12px;
  box-shadow: 0 1px 3px rgba(0,0,0,0.1);  /* Elevation */
}

.modal-overlay {
  background: rgba(0, 0, 0, 0.5);  /* Dim ground */
  backdrop-filter: blur(4px);      /* Blur ground */
}

共同區域

位於同一邊界內的元素會被視為同一群組。

將元素包覆在視覺容器中(卡片、方框、邊框區域),即可表示它們屬於同一群組。

連續性

眼睛會沿著路徑、線條和曲線移動。

善用對齊和視覺流向,引導使用者的注意力穿越您的介面。

CONTINUITY IN ALIGNMENT:
┌────────────────────────────────┐
 Logo    [Nav]  [Nav]  [Nav]      Aligned on horizontal axis
├────────────────────────────────┤
                                
 Headline                       
 ─────────────────────────────     Eye follows left edge
 Paragraph text continues       
 along the same left edge       
                                
 [Primary Action]                  Still on the left edge
└────────────────────────────────┘

封閉性

大腦會自動補全不完整的形狀。

使用者不需要看到每一個像素——他們會在腦中補全熟悉的形狀。這使得更簡約、更優雅的設計成為可能。

/* Horizontal scroll with partial card (closure) */
.card-carousel {
  display: flex;
  gap: 16px;
  overflow-x: auto;
  padding-right: 48px;  /* Show partial card = scroll hint */
}

.card-carousel .card {
  flex: 0 0 280px;  /* Fixed width, partial visible */
}

Gestalt 快速參考

原則 規則 主要用途
接近性 相關的靠近,不相關的拉遠 表單欄位、內容區塊
相似性 相同外觀=相同功能 按鈕、卡片、導覽列
圖與地 清楚的圖層分離 卡片、對話框、覆蓋層
共同區域 邊界將內容分組 設定區塊、使用者卡片
連續性 沿著線條與對齊移動 時間軸、閱讀流向
封閉性 大腦補全形狀 圖示、捲動提示、骨架畫面

字體排版

「字體排版是賦予人類語言持久視覺形式的工藝。」— Robert Bringhurst

字體排版是介面設計的基礎。文字傳達功能、層級與品牌。拙劣的字體排版讓介面更難使用;優秀的字體排版是隱形的——它就是自然而然地運作。

字級系統

一致的字級系統能創造視覺和諧。使用數學比例來建立。

1.25 比例(推薦用於 UI):

:root {
  /* Base: 16px (1rem) */
  --text-xs: 0.64rem;    /* 10.24px - use sparingly */
  --text-sm: 0.8rem;     /* 12.8px - captions, labels */
  --text-base: 1rem;     /* 16px - body text */
  --text-lg: 1.25rem;    /* 20px - lead text */
  --text-xl: 1.563rem;   /* 25px - h4 */
  --text-2xl: 1.953rem;  /* 31.25px - h3 */
  --text-3xl: 2.441rem;  /* 39px - h2 */
  --text-4xl: 3.052rem;  /* 48.8px - h1 */
}

行高(行距)

行高對可讀性有極大影響。不同的內容需要不同的行距。

內容類型 行高 原因
標題 1.1 - 1.2 緊密、粗體、短文字
UI 文字 1.3 - 1.4 標籤、按鈕
內文 1.5 - 1.7 可讀的段落
長篇內容 1.7 - 2.0 文章、技術文件

行寬(字元量測)

最佳行寬能避免眼睛疲勞並提升閱讀理解力。

  • 最佳範圍: 每行45至75個字元
  • 目標值: 50至65個字元
  • 絕對上限: 85個字元
p {
  max-width: 65ch;  /* ch unit = width of '0' character */
}

.article-body {
  max-width: 70ch;
  margin: 0 auto;
}

字型選擇

系統字型優先。 它們瞬間載入、符合平台風格,且針對螢幕進行了最佳化。

:root {
  --font-sans: system-ui, -apple-system, BlinkMacSystemFont,
               'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;

  --font-mono: ui-monospace, 'SF Mono', 'Cascadia Code',
               'JetBrains Mono', Consolas, monospace;
}

在以下情境使用自訂字型: - 品牌差異化(行銷網站) - 編輯/出版的質感 - 系統字型無法達成的特定設計意圖

利用字重建立層級

使用字重來建立層級,而不僅僅依賴字級。

h1 { font-weight: 700; }  /* Bold */
h2 { font-weight: 600; }  /* Semibold */
h3 { font-weight: 600; }  /* Semibold */
.lead { font-weight: 500; }  /* Medium */
p { font-weight: 400; }   /* Regular */
.meta { font-weight: 400; color: var(--text-muted); }

字體排版快速參考

屬性 內文 標題 UI 標籤
字級 16-18px 24-48px 12-14px
字重 400 600-700 500
行高 1.5-1.7 1.1-1.2 1.3-1.4
行寬 45-75ch 不適用 不適用
對齊 靠左 置中亦可 靠左

色彩理論

「色彩是一股直接影響靈魂的力量。」— Wassily Kandinsky

色彩的傳達速度勝過文字。它建立氛圍、引導注意力、傳遞意義,並塑造品牌識別。

60-30-10 法則

這是創造平衡介面最可靠的色彩分配法則。

┌──────────────────────────────────────────┐
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│ 60% - Dominant (Background)
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
│░░░░░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░░░░░░░│ 30% - Secondary (Cards, sections)
│░░░░░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░░░░░░░│
│░░░░░▓▓▓▓▓▓▓▓▓▓▓▓██████▓▓▓▓▓▓▓▓▓▓░░░░░░░░│ 10% - Accent (Buttons, links)
└──────────────────────────────────────────┘

建立色彩調色盤

每個介面都需要以下語意色彩:

:root {
  /* Brand */
  --color-primary: hsl(220, 80%, 50%);
  --color-primary-hover: hsl(220, 80%, 45%);

  /* Semantic */
  --color-success: hsl(142, 76%, 36%);  /* Green - positive */
  --color-warning: hsl(38, 92%, 50%);   /* Amber - caution */
  --color-error: hsl(0, 84%, 60%);      /* Red - danger */

  /* Neutrals */
  --color-background: hsl(0, 0%, 100%);
  --color-surface: hsl(220, 14%, 96%);
  --color-border: hsl(220, 13%, 91%);

  /* Text */
  --color-text: hsl(220, 13%, 13%);
  --color-text-secondary: hsl(220, 9%, 46%);
  --color-text-muted: hsl(220, 9%, 64%);
}

色彩心理學

色彩 心理效果 UI 用途
藍色 信任、穩定、沉穩 金融、科技、企業
綠色 成長、自然、成功 健康、環保、正面狀態
紅色 能量、緊迫、危險 警示、促銷、錯誤
橘色 溫暖、熱情 CTA、活潑品牌
黃色 樂觀、謹慎 警告、重點標示
紫色 奢華、創意 高端產品

深色模式優先設計(Vercel)

Vercel 先為深色模式設計,再衍生淺色模式。這種方式能產生更好的深色介面,因為深色模式成為首要考量,而非事後補做。

/* Design dark first, derive light */
:root {
  /* Dark mode defaults */
  --color-background: hsl(0, 0%, 0%);
  --color-surface: hsl(0, 0%, 7%);
  --color-border: hsl(0, 0%, 15%);
  --color-text: hsl(0, 0%, 93%);
  --color-text-secondary: hsl(0, 0%, 63%);
}

@media (prefers-color-scheme: light) {
  :root {
    --color-background: hsl(0, 0%, 100%);
    --color-surface: hsl(0, 0%, 97%);
    --color-border: hsl(0, 0%, 89%);
    --color-text: hsl(0, 0%, 9%);
    --color-text-secondary: hsl(0, 0%, 40%);
  }
}

適用情境: 開發者工具、媒體應用程式、儀表板——使用者長時間使用且深色模式可減輕眼睛疲勞的場景。

無障礙對比度

等級 一般文字 大型文字 UI 元件
AA 4.5:1 3:1 3:1
AAA 7:1 4.5:1 不適用

WCAG 2.2 於2025年10月成為 ISO 標準(ISO/IEC 40500:2025),新增了焦點可見性、冗餘輸入及無障礙認證等準則。主要新增內容:焦點指示器不得被其他內容完全遮蔽(2.4.11),認證機制不得僅依賴認知功能測試(3.3.8)。

工具: WebAIM Contrast Checker、Chrome DevTools 色彩選取器


視覺層級

「設計是品牌的無聲大使。」——Paul Rand

視覺層級控制使用者先看到什麼、接著看到什麼、最後看到什麼。缺乏清晰的層級,使用者必須費力尋找資訊。有了它,介面便顯得毫不費力。

層級的六大工具

1. 尺寸——較大的元素首先吸引注意力

.hero-title { font-size: 3rem; }      /* Dominant */
.section-title { font-size: 1.5rem; } /* Secondary */
.body-text { font-size: 1rem; }       /* Baseline */

2. 字重——粗體向前突出,細體向後退縮

h1 { font-weight: 700; }
.lead { font-weight: 500; }
p { font-weight: 400; }

3. 色彩與對比——高對比 = 注意力

.title { color: var(--color-text); }  /* Near black */
.meta { color: var(--color-text-muted); }  /* Gray */

4. 位置——關鍵位置至關重要

F 型模式(內容頁面):           Z 型模式(登陸頁面):
████████████████████████      1 ──────────────────► 2
████████                            ↘
████                                     ↘
██                                            ↘
                                   3 ──────────────────► 4

5. 留白——隔離創造重要性

.hero { padding: 120px 48px; }  /* Generous space */
.data-table { padding: 12px; }  /* Dense content */

6. 深度與高度——向前凸出的元素吸引注意力

:root {
  --shadow-sm: 0 1px 2px rgba(0,0,0,0.05);
  --shadow-md: 0 4px 6px rgba(0,0,0,0.1);
  --shadow-lg: 0 10px 15px rgba(0,0,0,0.1);
}

.card { box-shadow: var(--shadow-sm); }
.card:hover { box-shadow: var(--shadow-md); }
.modal { box-shadow: var(--shadow-lg); }

應用模式

協作在場感(Figma): 多位使用者的游標搭配名稱標籤、選取高亮及元件外框,共同構成一份活的文件。每位協作者的顏色各不相同但權重一致——沒有任何游標比其他的更「搶眼」。

環境狀態指示器(Vercel): 部署狀態使用細緻、持久的指示器,而非侵入式的警告。頂部一條細色條傳達狀態(建置中、已部署、失敗),不會打斷工作流程。

真實世界設計類比(Flighty): 航班進度視覺化模擬實體航空儀器——高度曲線、速度指示器和登機門地圖使用熟悉的視覺隱喻,而非抽象的進度條。

瞇眼測試

瞇起眼睛看您的設計。還能看到層級嗎?如果可以,那就是強而有力的層級。


間距與節奏

「留白就像空氣:設計需要它來呼吸。」——Wojciech Zieliński

間距是設計中看不見的結構。一致的間距創造視覺節奏——讓元素感覺彼此歸屬於一個連貫系統的感受。

8px 網格

8px 網格是業界標準,因為: - 可以均勻分割(8、16、24、32、40、48…) - 適用於常見的螢幕密度(1x、1.5x、2x、3x) - 無需計算即可創造一致的節奏

:root {
  --space-1: 4px;    /* Tight: icon gaps */
  --space-2: 8px;    /* Compact: inline elements */
  --space-3: 12px;   /* Snug: form fields */
  --space-4: 16px;   /* Default: most gaps */
  --space-6: 24px;   /* Spacious: card padding */
  --space-8: 32px;   /* Section gaps */
  --space-12: 48px;  /* Major sections */
  --space-16: 64px;  /* Page sections */
  --space-20: 80px;  /* Hero spacing */
}

內部間距與外部間距

內部(padding): 元素內部的空間 外部(margin): 元素之間的空間

原則: 在相關群組內,內部間距通常應大於外部間距。

.card {
  padding: 24px;        /* Internal: spacious */
  margin-bottom: 16px;  /* External: less than padding */
}

元件間距模式

卡片:

.card { padding: 24px; border-radius: 12px; }
.card-header { margin-bottom: 16px; }
.card-title { margin-bottom: 4px; }  /* Tight to subtitle */

按鈕:

.btn { padding: 12px 24px; border-radius: 8px; }
.btn--sm { padding: 8px 16px; }
.btn--lg { padding: 16px 32px; }
.btn-group { display: flex; gap: 12px; }

表單:

.form-row { margin-bottom: 24px; }
.form-label { margin-bottom: 4px; }
.form-help { margin-top: 4px; }
.form-actions { margin-top: 32px; display: flex; gap: 12px; }

間距速查表

情境 建議間距
圖示到文字 4-8px
標籤到輸入框 4px
表單群組之間 24px
卡片內距 20-24px
卡片間距 16-24px
區塊內距(行動裝置) 48-64px
區塊內距(桌面版) 80-96px
按鈕內距(水平/垂直) 24px / 12px

動畫原則

「動畫不是會動的繪圖藝術,而是被繪製出來的動態藝術。」——Norman McLaren

動畫為介面注入生命。做得好,它能引導注意力、傳達狀態並建立情感連結。做得差,則令人沮喪且分散注意力。

核心原則

動畫應該讓人感覺理所當然,而非裝飾性的。

好的動畫: 1. 傳達靜態設計無法表達的訊息 2. 透過展示關係來降低認知負荷 3. 感覺自然且在預期之中 4. 從意識層面消失

壞的動畫: 1. 存在只因為「看起來很酷」 2. 拖慢使用者的速度 3. 刻意吸引注意力 4. 製造焦慮或不耐煩

UI 關鍵原則

1. 預備動作——為使用者預告即將發生的事。

.button {
  transition: transform 0.1s ease-out;
}

.button:active {
  transform: scale(0.97);  /* Slight press before action */
}

2. 慣性延伸——讓運動以彈簧般的回彈自然完成。

.panel {
  transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
}
withAnimation(.spring(response: 0.4, dampingFraction: 0.7)) {
    isOpen = true
}

3. 緩入緩出——自然界中沒有東西以恆定速度運動。

曲線 使用時機 特性
ease-out 進入的元素 快速啟動,輕柔停止
ease-in 離開的元素 輕柔啟動,快速離開
ease-in-out 狀態變化 全程平滑
linear 載入指示器 持續且機械化

4. 舞台調度——將注意力導向重要的地方。除非經過精心編排為一組,否則同一時間只應有一個元素在移動。

5. 錯開排列——元素應依序出現,而非全部同時出現。

.list-item {
  animation: fadeSlideIn 0.3s ease-out both;
}

.list-item:nth-child(1) { animation-delay: 0ms; }
.list-item:nth-child(2) { animation-delay: 50ms; }
.list-item:nth-child(3) { animation-delay: 100ms; }
.list-item:nth-child(4) { animation-delay: 150ms; }

@keyframes fadeSlideIn {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
}

時間指南

持續時間 使用情境 感受
50-100ms 微互動(懸停、按壓) 即時回饋
150-200ms 簡單狀態變化(切換、選取) 俐落
250-350ms 中等過渡(面板滑動、卡片翻轉) 流暢
400-500ms 大幅度運動(頁面過渡、彈出視窗) 從容

效能:黃金法則

只對 transformopacity 做動畫——這些屬性由 GPU 加速,不會觸發版面重排。

/* BAD: Animating layout */
.panel { transition: left 0.3s, width 0.3s; }

/* GOOD: Using transform */
.panel { transition: transform 0.3s; }

何時不該使用動畫

  1. 使用者啟用了 prefers-reduced-motion css @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; } }

  2. 動畫不傳達任何資訊——無意義的旋轉、彈跳元素

  3. 使用者正在趕時間——錯誤狀態、表單驗證、搜尋結果
  4. 動畫會拖慢重複操作——鍵盤快捷鍵應跳過動畫
  5. 資料已經載入——Bear 透過預載內容實現零載入狀態,讓應用程式感覺即時。如果您可以預載,就完全跳過骨架畫面/載入指示器。
// Bear's approach: preload so no loading state is needed
struct NoteListView: View {
    @Query var notes: [Note]  // SwiftData loads from disk instantly
    // No loading state, no skeleton, no spinner — data is always there
    var body: some View {
        List(notes) { note in
            NoteRow(note: note)
        }
    }
}

動畫速查表

:root {
  /* Durations */
  --duration-instant: 0.1s;
  --duration-fast: 0.15s;
  --duration-normal: 0.25s;
  --duration-slow: 0.4s;

  /* Easings */
  --ease-out: cubic-bezier(0.0, 0.0, 0.58, 1.0);
  --ease-in: cubic-bezier(0.42, 0.0, 1.0, 1.0);
  --ease-in-out: cubic-bezier(0.42, 0.0, 0.58, 1.0);
  --ease-out-back: cubic-bezier(0.34, 1.56, 0.64, 1);
}

互動模式

「最好的介面就是沒有介面。」——Golden Krishna

互動模式定義了使用者如何操控、導覽及理解您的產品。這些模式是從研究那些提供卓越互動體驗的產品中萃取而來。

直接操控(Framer)

讓抽象概念變得具體可觸。Framer 將 CSS 斷點——抽象的數值——轉化為可拖曳的控制把手。使用者能即時看到版面配置的變化。

/* Breakpoint handle styling */
.breakpoint-handle {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 4px;
  background: var(--accent);
  cursor: col-resize;
  opacity: 0.6;
  transition: opacity 0.15s ease;
}

.breakpoint-handle:hover,
.breakpoint-handle:active {
  opacity: 1;
  width: 6px;
}

適用時機:任何結果為視覺化的設定——拖曳調整大小、色彩選取器、時間軸拖動瀏覽。

情境感知介面(Flighty、Figma)

只顯示當下相關的資訊。Flighty 針對航班追蹤使用了15種不同狀態。Figma 的屬性面板會根據您選取的物件完全變換。

階段(Flighty) 使用者看到的內容
起飛前24小時 確認碼、航廈資訊
在機場時 登機門編號、登機時間
飛行中 剩餘時間、進度、預計抵達時間
降落時 轉機登機門、步行路線
enum ContextState: CaseIterable {
    case farOut, dayBefore, headToAirport, atAirport
    case atGate, boarding, inFlight, landed, connection

    static func current(for flight: Flight, context: UserContext) -> ContextState {
        // Factor in: time, location, flight status
        // Return the single most relevant state
    }
}

反面模式:顯示所有控制項,並將不相關的灰色化。這會產生視覺噪音。

智慧啟動(Halide)

工具應該感知情境並自動啟動。Halide 的對焦放大鏡在拖曳對焦時出現,放開後消失。不需要切換按鈕。

struct IntelligentlyActivated<Content: View>: ViewModifier {
    let isInteracting: Bool
    @State private var isVisible = false

    func body(content: Content) -> some View {
        content
            .opacity(isVisible ? 1 : 0)
            .scaleEffect(isVisible ? 1 : 0.95)
            .animation(.easeInOut(duration: 0.2), value: isVisible)
            .onChange(of: isInteracting) { _, newValue in
                if newValue {
                    withAnimation { isVisible = true }
                } else {
                    DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
                        if !isInteracting { isVisible = false }
                    }
                }
            }
    }
}

雙模式設計(Halide、Warp)

模式切換應該轉換整個 UI,而不僅僅是切換元素。Halide 的自動模式和手動模式是完全不同的介面。Warp 透過四種輸入方式(打字、命令面板、AI、滑鼠)橋接 CLI 與 GUI,而不強迫使用者只能使用單一範式。

結構化內容(Warp、Bear、Craft)

為傳統上非結構化的內容增加結構。Warp 將終端機輸出轉化為獨立的區塊,可以複製、分享或重新執行。Bear 讓您在撰寫時即時組織筆記(#tag/subtag)。Craft 讓任何區塊都能成為一個頁面——結構從使用中自然浮現,而非預先定義的層級架構。

漸進式訓練(Superhuman)

透過反覆接觸教導使用者更快的操作方式。Superhuman 的 Cmd+K 命令面板總是在搜尋結果旁顯示鍵盤快捷鍵。每次使用都是一堂微型課程。

/* Always show shortcut alongside command name */
.command-result {
  display: flex;
  justify-content: space-between;
  padding: 8px 12px;
}

.command-shortcut {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text-muted);
  background: var(--bg-subtle);
  padding: 2px 6px;
  border-radius: 4px;
}

反面模式:用教學彈窗來解釋功能。解說會被遺忘;實際操作才會被記住。


AI 介面模式

「最好的 AI 介面讓機器的過程可見,讓機器的產出可驗證。」

AI 介面面臨獨特的挑戰:使用者無法預測輸出、無法透過目視檢查驗證正確性,而且通常無法判斷系統是在正常運作還是已經故障。

核心問題

傳統軟體 AI 軟體
輸出可預測 輸出會變化
錯誤顯而易見 錯誤看起來合理
使用者透過測試來驗證 使用者透過查核來源來驗證
載入中=等待 載入中=運算中(要展示出來)
預設信任 信任需要贏取

引用優先設計(Perplexity)

每一項事實性陳述都必須連結到其來源。Perplexity 在每個論述中嵌入行內引用 [1],搭配懸停預覽及常駐的來源面板。

.citation-marker {
  position: relative;
  color: var(--accent);
  cursor: pointer;
  font-size: 0.8em;
  vertical-align: super;
}

.citation-preview {
  position: absolute;
  bottom: 100%;
  left: 50%;
  transform: translateX(-50%);
  width: 280px;
  padding: 12px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

反面模式:AI 介面生成論述卻沒有可追溯的來源。如果模型無法引用出處,介面就應該標記出來。

串流階段指示器(Perplexity)

向使用者展示 AI 正在做什麼,而不只是顯示它正在運作。用階段指示器取代通用的載入動畫:「搜尋中…」→「正在閱讀4個來源…」→「撰寫回答中…」

.phase-indicator {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  background: color-mix(in srgb, var(--phase-color) 10%, transparent);
  border-radius: 16px;
  font-size: 13px;
  color: var(--phase-color);
  transition: all 0.3s ease;
}

.loading-dots span {
  width: 4px;
  height: 4px;
  background: currentColor;
  border-radius: 50%;
  animation: pulse 1.4s ease-in-out infinite;
}

錯誤透明度

當 AI 失敗或不確定時,清楚地展示出來——不要躲在聽起來很有信心的文字背後。

情境 錯誤模式 正確模式
低信心度 自信地陳述 「我不確定,但…」搭配較低調的樣式
找不到來源 捏造文字 「我找不到這項論述的來源」
來源互相矛盾 默默選擇其一 同時顯示兩者並標記衝突
過時資訊 當作最新的呈現 「截至[日期]…」搭配時效性指標

關鍵洞察:使用者會原諒坦承不確定的 AI。但不會原諒自信滿滿卻答錯的 AI。


Dieter Rams:十大原則

「少,但更好。」——Dieter Rams

Dieter Rams 是20世紀最具影響力的工業設計師。他於1961年至1995年間擔任 Braun 設計主管,創造出歷經數十年依然歷久彌新的產品。他的作品直接啟發了 Apple 的設計語言。

優秀設計的十大原則

1. 優秀的設計是創新的 不要複製。將先進科技與創新設計結合。

2. 優秀的設計使產品有用 每個元素都必須有其用途。形式追隨功能。

3. 優秀的設計是美觀的 美不是膚淺的——它是本質。我們每天使用的產品影響著我們的幸福感。

4. 優秀的設計使產品容易理解 使用者不應該需要說明書。介面本身就是教學。

5. 優秀的設計是不張揚的 設計應該支持而非壓迫使用者。使用者的內容才是主角,而非您的 UI。

/* Obtrusive: UI competes with content */
.editor {
  background: linear-gradient(135deg, purple, blue);
  border: 3px dashed gold;
}

/* Unobtrusive: UI recedes, content shines */
.editor {
  background: var(--color-background);
  border: 1px solid var(--color-border);
}

6. 優秀的設計是誠實的 不使用暗黑模式(dark patterns)。不過度承諾。對限制保持透明。

7. 優秀的設計是持久的 避免會迅速過時的潮流。選擇經典而非時髦。

TRENDY (will date):           TIMELESS:
- Extreme glassmorphism       - Clean typography
- Neon colors, glitch effects - Subtle elevation
- Aggressive gradients        - Neutral palette with considered accent

8. 優秀的設計在每個細節上都是徹底的 沒有任何東西可以是隨意的。載入狀態、空白狀態、錯誤狀態——全都需要精心設計。

9. 優秀的設計是環保的 效能就是環保。尊重使用者的注意力。撰寫高效率的程式碼。

10. 優秀的設計是盡可能少的設計 移除一切非必要的東西。最好的設計是隱形的。


2026年網頁設計模式

現代網頁設計善用原生 CSS 功能,在許多情境下不再需要 JavaScript。2025至2026年間,anchor positioning、scroll-driven animations 以及 @starting-style 已正式進入主流瀏覽器。

Container Queries

根據元件的容器大小來調整尺寸,而非依賴視窗大小。

.card-grid {
  container-type: inline-size;
  container-name: card-grid;
}

.card {
  display: grid;
  gap: 16px;
  padding: 20px;
}

@container card-grid (min-width: 400px) {
  .card {
    grid-template-columns: auto 1fr;
  }
}

@container card-grid (min-width: 600px) {
  .card {
    padding: 32px;
    gap: 24px;
  }
}

:has() 選擇器

根據子元素選取父元素——過去若不使用 JavaScript 根本無法實現。

/* Card with image gets different padding */
.card:has(img) {
  padding: 0;
}

.card:has(img) .card-content {
  padding: 20px;
}

/* Form group with error */
.form-group:has(.input:invalid) .form-label {
  color: var(--color-error);
}

/* Highlight navigation when on that page */
.nav-item:has(a[aria-current="page"]) {
  background: var(--color-surface);
}

CSS 巢狀結構

原生巢狀語法,不再需要預處理器。

.card {
  background: var(--color-surface);
  border-radius: 12px;
  padding: 24px;

  & .card-title {
    font-size: 1.25rem;
    font-weight: 600;
    margin-bottom: 8px;
  }

  & .card-body {
    color: var(--color-text-secondary);
    line-height: 1.6;
  }

  &:hover {
    box-shadow: var(--shadow-md);
  }

  @media (min-width: 768px) {
    padding: 32px;
  }
}

HTMX 整合

以伺服器驅動的互動方式,無需笨重的 JavaScript 框架。

<!-- Load content on click -->
<button hx-get="/api/more-items"
        hx-target="#item-list"
        hx-swap="beforeend"
        hx-indicator="#loading">
  Load More
</button>

<!-- Form with inline validation -->
<form hx-post="/api/contact"
      hx-target="#form-response"
      hx-swap="outerHTML">
  <input type="email" name="email"
         hx-post="/api/validate-email"
         hx-trigger="blur"
         hx-target="next .error" />
  <span class="error"></span>
</form>

Anchor Positioning

原生 CSS 定位機制,可將一個元素相對於另一個元素進行定位——完全不需要 JavaScript。工具提示、彈出視窗和下拉選單都能自動跟隨其觸發元素。

/* Anchor an element to another */
.trigger {
  anchor-name: --my-trigger;
}

.tooltip {
  position: fixed;
  position-anchor: --my-trigger;
  top: anchor(bottom);
  left: anchor(center);
  translate: -50% 8px;
}

Scroll-Driven Animations

將動畫進度與捲動位置綁定。閱讀進度指示器、視差效果和漸進顯示序列,全部無需 JavaScript。

/* Reading progress bar */
.progress-bar {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 3px;
  background: var(--color-primary);
  transform-origin: left;
  animation: progress linear;
  animation-timeline: scroll();
}

@keyframes progress {
  from { transform: scaleX(0); }
  to { transform: scaleX(1); }
}

@starting-style

為新加入 DOM 的元素定義初始樣式——實現純 CSS 進場動畫,無需 JavaScript。

.card {
  opacity: 1;
  transform: translateY(0);
  transition: opacity 0.3s ease, transform 0.3s ease;

  @starting-style {
    opacity: 0;
    transform: translateY(10px);
  }
}

Design Tokens 系統

一套完整的 token 系統,確保整個應用程式的一致性。

:root {
  /* Colors */
  --color-text: #1a1a1a;
  --color-text-secondary: #666666;
  --color-text-muted: #999999;

  --color-background: #ffffff;
  --color-surface: #f8f9fa;
  --color-surface-elevated: #ffffff;

  --color-border: #e5e7eb;
  --color-primary: #3b82f6;
  --color-primary-hover: #2563eb;

  --color-success: #10b981;
  --color-warning: #f59e0b;
  --color-error: #ef4444;

  /* Typography */
  --font-sans: system-ui, -apple-system, sans-serif;
  --font-mono: "SF Mono", Consolas, monospace;

  --text-xs: 0.75rem;
  --text-sm: 0.875rem;
  --text-base: 1rem;
  --text-lg: 1.125rem;
  --text-xl: 1.25rem;
  --text-2xl: 1.5rem;
  --text-3xl: 2rem;

  --leading-tight: 1.25;
  --leading-normal: 1.5;
  --leading-relaxed: 1.75;

  /* Spacing (8px base) */
  --space-1: 0.25rem;   /* 4px */
  --space-2: 0.5rem;    /* 8px */
  --space-3: 0.75rem;   /* 12px */
  --space-4: 1rem;      /* 16px */
  --space-6: 1.5rem;    /* 24px */
  --space-8: 2rem;      /* 32px */
  --space-12: 3rem;     /* 48px */
  --space-16: 4rem;     /* 64px */

  /* Borders */
  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 12px;
  --radius-full: 9999px;

  /* Shadows */
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
  --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.07);
  --shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1);

  /* Transitions */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --duration-fast: 100ms;
  --duration-normal: 200ms;
}

正確實作深色模式

不要單純反轉色彩——請針對深色情境重新設計。

@media (prefers-color-scheme: dark) {
  :root {
    /* Neutrals */
    --color-background: hsl(220, 13%, 10%);
    --color-surface: hsl(220, 13%, 15%);
    --color-surface-elevated: hsl(220, 13%, 18%);
    --color-border: hsl(220, 13%, 23%);

    /* Text (inverted) */
    --color-text: hsl(220, 9%, 93%);
    --color-text-secondary: hsl(220, 9%, 70%);
    --color-text-muted: hsl(220, 9%, 55%);

    /* Adjust saturation for dark mode */
    --color-primary: hsl(220, 80%, 60%);
    --color-success: hsl(142, 70%, 45%);
    --color-error: hsl(0, 80%, 65%);

    /* Shadows in dark mode need adjustment */
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
    --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.4);
  }
}

深色模式原則: - 大面積區域降低飽和度 - 提高強調色的明度 - 加強陰影效果(深色模式下需要更高的對比度) - 將深色模式視為刻意的設計,而非事後補救


Figma 匯出工作流程

將設計檔案轉換為生產程式碼,需要系統性地提取 design tokens——顏色、字型、間距和效果,這些定義了您的設計語言。

Figma Variables 匯出

Figma 原生的 Variables 功能提供最簡潔的提取路徑:

匯出步驟: 1. 開啟 Figma 檔案 → Local Variables 面板 2. 點擊集合選單 →「Export to JSON」 3. 儲存為 figma-variables.json

JSON Token 結構:

{
  "colors": {
    "primitive": {
      "blue-500": { "value": "#3b82f6", "type": "color" },
      "blue-600": { "value": "#2563eb", "type": "color" }
    },
    "semantic": {
      "primary": { "value": "{colors.primitive.blue-500}", "type": "color" },
      "primary-hover": { "value": "{colors.primitive.blue-600}", "type": "color" }
    }
  },
  "spacing": {
    "1": { "value": "4px", "type": "spacing" },
    "2": { "value": "8px", "type": "spacing" },
    "4": { "value": "16px", "type": "spacing" }
  }
}

Token 轉換為 CSS

CSS Custom Properties:

:root {
  /* Primitive colors (direct values) */
  --color-blue-50: #eff6ff;
  --color-blue-100: #dbeafe;
  --color-blue-500: #3b82f6;
  --color-blue-600: #2563eb;
  --color-blue-900: #1e3a8a;

  /* Semantic colors (reference primitives) */
  --color-primary: var(--color-blue-500);
  --color-primary-hover: var(--color-blue-600);
  --color-background: var(--color-white);
  --color-surface: var(--color-gray-50);

  /* Spacing (8px grid) */
  --space-1: 0.25rem;  /* 4px */
  --space-2: 0.5rem;   /* 8px */
  --space-4: 1rem;     /* 16px */
  --space-6: 1.5rem;   /* 24px */
  --space-8: 2rem;     /* 32px */

  /* Typography */
  --font-size-sm: 0.875rem;
  --font-size-base: 1rem;
  --font-size-lg: 1.125rem;
  --line-height-tight: 1.25;
  --line-height-normal: 1.5;

  /* Effects */
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
  --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.07);
  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 12px;
}

深色模式 Tokens:

@media (prefers-color-scheme: dark) {
  :root {
    --color-background: var(--color-gray-900);
    --color-surface: var(--color-gray-800);
    --color-text: var(--color-gray-100);
    --color-text-secondary: var(--color-gray-400);

    /* Adjusted shadows for dark mode */
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
    --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.4);
  }
}

Token 轉換為 SwiftUI

Color 擴充:

import SwiftUI

extension Color {
    // MARK: - Primitive Colors
    static let blue50 = Color(hex: "eff6ff")
    static let blue500 = Color(hex: "3b82f6")
    static let blue600 = Color(hex: "2563eb")

    // MARK: - Semantic Colors
    static let brandPrimary = Color.blue500
    static let brandPrimaryHover = Color.blue600

    // MARK: - Surface Colors
    static let surfaceBackground = Color(light: .white, dark: Color(hex: "0f172a"))
    static let surfaceElevated = Color(light: Color(hex: "f8fafc"), dark: Color(hex: "1e293b"))
}

extension Color {
    init(hex: String) {
        // Standard hex parsing implementation
    }

    init(light: Color, dark: Color) {
        self.init(UIColor { traits in
            traits.userInterfaceStyle == .dark ? UIColor(dark) : UIColor(light)
        })
    }
}

間距常數:

enum Spacing {
    static let xs: CGFloat = 4    // --space-1
    static let sm: CGFloat = 8    // --space-2
    static let md: CGFloat = 16   // --space-4
    static let lg: CGFloat = 24   // --space-6
    static let xl: CGFloat = 32   // --space-8
}

// Usage
VStack(spacing: Spacing.md) {
    // ...
}
.padding(Spacing.lg)

設計師交付清單

設計師應匯出的內容:

資源類型 格式 備註
顏色 Variables JSON 包含淺色與深色模式
字型排版 Styles 匯出 字型、大小、粗細、行高
間距 Variables JSON 基礎單位需記錄
圖示 SVG 描邊樣式、單色
圖片 PNG @2x/@3x 或 WebP 含壓縮設定
元件 Figma 連結 供開發實作時參考

品質關卡標準:

  • [ ] 所有顏色皆定義為變數(無硬編碼 hex 值)
  • [ ] 字型排版使用已定義的文字樣式
  • [ ] 間距遵循網格系統(以 8px 為基礎)
  • [ ] 提供深色模式變體
  • [ ] 互動狀態已記錄(hover、active、disabled)
  • [ ] 響應式斷點已標註
  • [ ] 無障礙需求已註明(對比度比值)

開發者收到的交付物:

  1. Token 檔案(JSON/CSS/Swift,依平台而定)
  2. 元件規格與尺寸標註
  3. 所需格式的資源匯出檔
  4. 互動文件(狀態、動畫)
  5. 無障礙標註

快速參考表

Gestalt 原則

原則 規則 用途
鄰近性 相關的元素放在一起 表單、區塊
相似性 外觀相同代表功能相同 按鈕、卡片
圖地關係 清晰的層次分離 彈出視窗、卡片
連續性 視覺沿著線條延伸 時間軸、對齊
閉合性 大腦會補完未完成的形狀 圖示、捲動提示

字型排版

元素 大小 粗細 行高
內文 16px 400 1.5-1.7
標題 24-48px 600-700 1.1-1.2
UI 標籤 12-14px 500 1.3-1.4
說明文字 12px 400 1.4

色彩角色

角色 淺色模式 深色模式
背景 #ffffff #0f172a
表面 #f4f5f7 #1e293b
邊框 #e4e6ea #334155
文字 #1a1a2e #f1f5f9
次要文字 #6b7280 #94a3b8
主色 #3b82f6 #60a5fa
成功 #22c55e #4ade80
錯誤 #ef4444 #f87171

間距比例

Token 用途
–space-1 4px 圖示間距
–space-2 8px 行內元素
–space-4 16px 預設間距
–space-6 24px 卡片內距
–space-8 32px 區塊間距
–space-16 64px 頁面區段

設計檢查清單

在發布任何介面之前,請確認以下項目:

Gestalt

  • [ ] 相關元素之間的距離比無關元素更近(接近性)
  • [ ] 功能相似的元素具有相似的樣式(相似性)
  • [ ] 前景與背景之間有清晰的區分(圖地關係)
  • [ ] 視線能自然地流過版面(連續性)

字體排印

  • [ ] 基礎字體大小至少為 16px
  • [ ] 內文行高達 1.5 以上
  • [ ] 每行字數不超過 75 個字元
  • [ ] 層次分明(可區分 3 個層級)
  • [ ] 全站使用一致的字級比例

色彩

  • [ ] 所有文字通過 4.5:1 對比度標準(WCAG AA)
  • [ ] 色彩不是唯一的資訊指示方式(搭配圖示/標籤)
  • [ ] 深色模式經過刻意設計
  • [ ] 遵循 60-30-10 色彩分配原則

視覺層次

  • [ ] 能夠辨識出最重要的第一元素
  • [ ] 視線按照預期順序流動
  • [ ] 每個區塊只有一個明確的 CTA
  • [ ] 字級比例保持一致

間距

  • [ ] 所有間距使用已定義的比例(不使用隨意數值)
  • [ ] 卡片/元件具有一致的內距
  • [ ] 行動裝置的間距舒適
  • [ ] 網格對齊一致(以 8px 為基準)

互動

  • [ ] 使用者能否在不思考工具本身的情況下達成目標?
  • [ ] UI 是否能適應目前的情境?
  • [ ] 工具是否只在相關時才顯示?
  • [ ] 重複使用是否能引導使用者學會更快的操作方式?

AI 介面

  • [ ] 每個事實陳述都有可追溯的來源
  • [ ] 串流顯示處理階段,而非僅呈現載入動畫
  • [ ] 錯誤狀態透明呈現,而非隱藏
  • [ ] 低信心度的輸出在視覺上有所區別

Dieter Rams 檢驗

  • [ ] 是否還有可以移除的東西?
  • [ ] 每個元素是否都具有功能?
  • [ ] 5 年後這個設計是否會顯得過時?
  • [ ] 是否設計了所有狀態?

資源

書籍: - As Little Design as Possible,Sophie Lovell 著(Dieter Rams) - The Elements of Typographic Style,Robert Bringhurst 著

工具: - WebAIM Contrast Checker - Type Scale Generator - Figma Tokens Studio — Design token 管理工具

設計系統: - Apple HIG - Material Design 3 - Radix UI - shadcn/ui


設計研究

深入分析 16 款卓越產品,記錄值得借鏡的設計模式與原則。

開發者工具

產品 關鍵貢獻
Figma 多人協作呈現、情境感知面板
Warp 區塊式終端機、CLI-GUI 橋接
Framer 視覺化響應式設計、屬性控制
Vercel 卓越的深色模式、環境狀態指示
Linear Optimistic UI、鍵盤優先工作流程
Raycast 擴充系統、快速操作

iOS 原生應用(Apple Design Award 得獎作品)

產品 關鍵貢獻
Flighty 15 種智慧狀態、Live Activities、資料視覺化
Halide 智慧啟動、手勢控制
Bear 字體排印優先、行內標籤
Craft 原生優先的跨平台設計、巢狀頁面
Things 延遲日期、快速輸入模式

生產力與 AI

產品 關鍵貢獻
Superhuman 100ms 法則、命令面板訓練、實踐式入門引導
Perplexity 引用優先的 AI、串流階段
Notion 區塊系統、斜線命令
Arc 空間、分割視圖、命令列
Stripe 卓越的技術文件、API 設計

本指南透過實踐不斷成長。設計原則是永恆的,但其應用方式會隨著技術與理解而持續演進。