軟體工程師的設計原則
專為軟體工程師整理的設計基礎:涵蓋字體排印、色彩、間距、動畫、AI介面模式、設計權杖,以及48個當代產品案例研究。
更新於2026年8月18日
2026年5月18日更新:更新「設計研究」索引,使其與目前涵蓋48項研究的內容一致,並擴充「AI介面模式」,納入代理式工作流程的實證:檢查點、核准狀態、來源可信度,以及清楚可見的驗證結果。
2026年5月更新:新增關於WCAG 3.0於2026年3月發布之工作草案的說明,以及W3C認為WCAG 2.2與3.0將並行使用的立場。目前進行無障礙工作時,仍應以WCAG 2.2為目標標準。
2026年2月更新:新增兩個章節——互動模式(從研究Framer、Flighty、Halide、Warp、Bear、Craft與Superhuman歸納出的8種典範)以及AI介面模式(以引用為優先的設計、串流階段,以及從Perplexity歸納出的錯誤透明度)。將網頁模式更新至2026年,納入錨點定位、捲動驅動動畫與@starting-style。更新無障礙內容,以反映WCAG 2.2已成為ISO標準。若要深入瞭解48款卓越產品,請參閱設計研究。
多年來,我一邊開發軟體,一邊鑽研設計;不僅汲取Dieter Rams等傳奇人物的設計原則,也深入剖析Linear、Stripe與Raycast等產品的介面。本指南將這些理解去蕪存菁,彙整成一份完整的參考資料——正是我剛開始重視軟體外觀與使用感受時,希望有人已經寫好的指南。
設計不是裝飾,而是溝通。每個像素都在傳達功能、層級與意義。業餘軟體與專業軟體之間的差異,在於是否理解這些原則,並能始終如一地加以運用。
本指南假設您已具備撰寫程式碼的能力。它要教您如何觀察——理解為什麼有些介面用起來毫不費力,有些卻令人無所適從;更重要的是,如何打造前者。
目錄
第一部分:基礎篇
第二部分:互動與 AI
第三部分:設計哲學
第四部分:實作篇
第五部分:參考資源
Gestalt 心理學
「整體不同於各部分的總和。」— Kurt Koffka
Gestalt 心理學發源於 1920 年代的德國,旨在解釋人類如何感知視覺資訊。大腦並非逐一辨識像素,而是將元素組織成有意義的模式。掌握這些原則,便能主導使用者對介面的認知方式。
鄰近性(Proximity)
彼此靠近的元素會被視為一組。
這是 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("you@example.com", text: $email)
.textFieldStyle(.roundedBorder)
}
.padding(.bottom, 24) // Wide between groups
相似性(Similarity)
具有相同視覺特徵的元素會被認為彼此相關。
當元素外觀一致時,使用者會假設它們的功能也相同。這正是設計系統採用一致按鈕樣式、卡片處理方式和字型排版的原因。
Example Navigation:
┌───────────────────────────────────┐
│ [Dashboard] [Projects] [Settings] │ ← Same style = same function
│ │
│ ┌─────┐ ┌─────┐ ┌─────┐ │
│ │Card │ │Card │ │Card │ │ ← Same style = same content type
│ └─────┘ └─────┘ └─────┘ │
│ │
│ [+ New Project] │ ← Different style = different function
└───────────────────────────────────┘
圖地關係(Figure-Ground)
內容應與背景明確區隔。
大腦需要區分「圖」(聚焦對象)與「地」(背景)。圖地關係處理不當會造成視覺混亂。
常用手法: - 對比(淺色圖形搭配深色背景,或反之) - 陰影(將圖形提升至背景之上) - 邊框(界定圖形邊緣) - 模糊(模糊背景、銳化前景)
/* 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 */
}
共同區域(Common Region)
位於同一邊界內的元素會被視為同一群組。
將元素包圍在視覺容器中(卡片、方框、邊框區域),即暗示它們彼此關聯。
連續性(Continuity)
視線會自然沿著路徑、線條與曲線移動。
善用對齊與視覺動線,引導使用者的注意力流動於介面之中。
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
└────────────────────────────────┘
封閉性(Closure)
大腦會自動補全不完整的形狀。
使用者不需要看到每一個像素——他們會在腦中自動補完熟悉的形狀。這使得更簡約、更優雅的設計成為可能。
/* 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
字型排版是介面設計的根基。文字傳遞功能、層級與品牌特質。拙劣的排版讓介面更難使用;出色的排版則渾然天成——使用者甚至察覺不到它的存在。
字級系統(Type Scale)
一致的字級系統能營造視覺和諧感,建議採用數學比例來建構。
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 */
}
行高(Leading)
行高對可讀性影響甚鉅,不同類型的內容需要不同的行距設定。
| 內容類型 | 行高 | 原因 |
|---|---|---|
| 標題 | 1.1 - 1.2 | 緊湊、粗體、篇幅短 |
| UI 文字 | 1.3 - 1.4 | 標籤、按鈕 |
| 內文 | 1.5 - 1.7 | 確保段落的可讀性 |
| 長篇閱讀 | 1.7 - 2.0 | 文章、技術文件 |
行寬(Measure)
最佳行寬能減少視覺疲勞,提升閱讀理解力。
- 最佳範圍:每行 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 | N/A |
| WCAG 2.2於2025年10月成為ISO標準(ISO/IEC 40500:2025),新增焦點可見性、重複輸入與無障礙驗證等準則。主要新增項目包括:焦點指示器不得被其他內容完全遮蔽(2.4.11),且驗證不得僅依賴認知功能測試(3.3.8)。W3C於2024年12月發布更新版WCAG 2.2,預計將於2026年底前以ISO/IEC 40500:2026發布。 |
WCAG 3.0仍是工作草案。最新修訂版已於2026年3月發布,且不會取代WCAG 2.2;W3C表示這兩項標準將會並存。無障礙指南工作小組計畫在2026年發布預估的WCAG 3時程,但目前的工作仍應以WCAG 2.2為目標標準。
工具:WebAIM Contrast Checker、Chrome DevTools色彩選擇器
視覺層級
「設計是品牌的無聲大使。」——Paul Rand
視覺層級控制使用者第一眼、第二眼、第三眼會看到什麼。缺乏清楚層級時,使用者必須費心尋找資訊。有了明確層級,介面就會顯得毫不費力。
視覺層級的6項工具
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-PATTERN (content pages): Z-PATTERN (landing pages):
████████████████████████ 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): 航班進度視覺化呼應實體航空儀表:高度曲線、速度指示器與登機門地圖,都使用熟悉的視覺隱喻,而非抽象的進度列。
瞇眼測試
瞇眼看您的設計。仍然看得出層級嗎?如果看得出來,就表示層級夠明確。
間距與節奏
「Whitespace就像空氣:設計需要它,才能呼吸。」——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. 預備動作(Anticipation) —— 為即將發生的事做好心理準備。
.button {
transition: transform 0.1s ease-out;
}
.button:active {
transform: scale(0.97); /* Slight press before action */
}
2. 跟隨動作(Follow-Through) —— 讓動態自然完成,如彈簧般漸趨穩定。
.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-In, Ease-Out) —— 自然界中沒有東西以恆速運動。
| 曲線 | 使用時機 | 特性 |
|---|---|---|
ease-out |
元素進場 | 快速啟動,緩慢停止 |
ease-in |
元素離場 | 緩慢啟動,快速離開 |
ease-in-out |
狀態切換 | 全程平滑 |
linear |
載入指示器 | 持續、機械式 |
4. 場景調度(Staging) —— 將注意力引導至重要之處。除非經過編排的群組動畫,否則同一時間只應有一個元素在移動。
5. 交錯排列(Staggering) —— 元素應依序出現,而非同時湧入。
.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 | 大幅移動(頁面過渡、彈出視窗) | 從容 |
效能:黃金法則
只對 transform 和 opacity 做動畫 —— 這兩者經過GPU加速,不會觸發重新佈局。
/* BAD: Animating layout */
.panel { transition: left 0.3s, width 0.3s; }
/* GOOD: Using transform */
.panel { transition: transform 0.3s; }
何時不該使用動畫
-
使用者啟用了
prefers-reduced-motioncss @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; } } -
動畫未提供額外資訊 —— 多餘的旋轉圖示、彈跳元素
- 使用者趕時間 —— 錯誤狀態、表單驗證、搜尋結果
- 動畫會拖慢重複操作 —— 鍵盤快捷鍵應跳過動畫
- 資料已經載入 —— 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)
模式切換應該徹底改變介面,而非僅僅切換元素的顯示與隱藏。Halide 的自動模式和手動模式是截然不同的兩套介面。Warp 透過四種輸入方式(打字、指令面板、AI、滑鼠)巧妙地橋接了CLI與圖形介面,不強迫使用者侷限於單一操作範式。
結構化內容(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。
代理式工作流程證據
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. 優良設計誠實不欺 不要使用暗黑模式。不要誇大承諾。坦誠說明限制。
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 年 Web 模式
原生 CSS 如今已能取代 JavaScript,解決愈來愈多版面配置與互動問題。2025 至 2026 年間,錨點定位、捲動驅動動畫與 @starting-style 陸續進入正式版瀏覽器;到了 2026 年中,又新增表單控制項自動調整大小、間隙裝飾與文字自動適應等功能。
在此,支援狀態比新穎程度更重要。僅在單一引擎推出的功能應視為漸進增強;達到 Baseline Newly available 的功能則可放心作為建置基礎。下表列出截至 2026 年 8 月兩者的差異。
| 功能 | Chrome | Firefox | Safari | 狀態 |
|---|---|---|---|---|
field-sizing |
123 | 152 | 26.2 | Baseline Newly available |
shape-outside: rect() / xywh() |
149 | 149 | 17.2 | Baseline Newly available |
background-clip: border-area |
150 | — | 18.2 | 兩個引擎 |
間隙裝飾(grid/flex 中的 column-rule) |
149 | — | — | 僅限 Chrome |
text-fit |
150 | — | — | 僅限 Chrome |
focusgroup |
150 | — | — | 僅限 Chrome |
來源:web.dev 的六月 Web 平台新功能與七月。
容器查詢
根據元件所在容器而非視窗大小,決定元件尺寸。
.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;
}
}
間隙裝飾
Grid 與 flex 的間隙如今可以套用專屬線條,因此分隔線不再需要偽元素、為每個子元素加上框線,或為每欄建立包裝元素。此功能僅支援 Chrome 149 以上版本,應視為漸進增強,而非版面的基礎。
.pricing-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 32px;
/* Vertical rules between columns, horizontal between rows */
column-rule: 1px solid var(--color-border);
row-rule: 1px solid var(--color-border);
}
舊作法會在除第一個項目外的每個項目加上 border-left,但只要 grid 換行至第二列,版面便會出錯。間隙裝飾直接繪製在間隙內,因此換行後仍能維持正確效果。
由於目前僅有單一引擎支援,請將這些線條純粹視為裝飾,切勿用來區分內容含義。若缺少線條便會導致版面語意不清,那麼這個版面在 Firefox 與 Safari 中就等同失效。
配合內容調整大小的表單控制項
field-sizing: content 可讓輸入欄位、文字區域與選取控制項隨使用者輸入的內容伸縮,取代幾乎每個程式碼庫都會重複實作的捲動高度 JavaScript。
.comment-box {
field-sizing: content;
min-height: 3lh; /* floor: three lines */
max-height: 12lh; /* ceiling: then scroll */
}
.tag-input {
field-sizing: content;
min-width: 8ch;
}
務必搭配 min-/max- 範圍限制。若未設定下限,空白欄位會縮到幾乎消失;若未設定上限,貼入大量文字可能會將提交按鈕推到畫面之外。
此功能已於 2026 年 6 月達到 Baseline Newly available,因此可安心作為主要機制,而不只是漸進增強。
自動適應容器的文字
text-fit 會縮放字型大小,使文字填滿容器寬度,適用於展示型標題與儀表板大型數字等過去需要量測指令碼的情境。
.stat-value {
text-fit: consistent; /* one size for the whole box */
}
目前僅支援 Chrome 150。請先設定一般的 font-size,讓其他引擎採用經過設計的尺寸,而非預設值:
.stat-value {
font-size: clamp(2rem, 8vw, 6rem); /* the real answer everywhere */
text-fit: consistent; /* refinement where supported */
}
clamp() 已能處理多數使用者想透過此功能解決的情境,而且所有主流瀏覽器皆支援。只有當內容長度變化幅度大到單一 clamp 無法妥善處理時,才建議採用 text-fit。
不需變通技巧的漸層框線
background-clip: border-area 會將背景繪製至框線區域,讓漸層框線只需兩行規則,不再需要巢狀元素或 mask-composite 技巧。
.featured-card {
border: 2px solid transparent;
border-radius: 12px;
background:
linear-gradient(var(--color-surface), var(--color-surface)) padding-box,
linear-gradient(135deg, #6366f1, #ec4899) border-area;
}
Chrome 150 與 Safari 18.2 已支援此功能;Firefox 尚未推出。請先宣告純色 border-color,確保後備效果是實際可見的框線,而非透明框線。
不需 Keydown 處理常式的方向鍵導覽
focusgroup 屬性會告知瀏覽器,一組控制項應視為單一鍵盤操作單元:按 Tab 鍵只會進入群組一次,方向鍵可在群組內移動,而再次按 Tab 鍵則會離開群組。工具列、分頁列、分段控制項及單選按鈕形式的按鈕群組都需要這種行為,而這也是自行打造元件時最常出錯的部分。
<div role="toolbar" focusgroup="wrap">
<button>Bold</button>
<button>Italic</button>
<button>Underline</button>
</div>
wrap 會讓使用者從最後一個項目按方向鍵後返回第一個項目。預設行為則會在兩端停止。
目前僅支援 Chrome 150,因此在支援範圍擴大前,請保留既有的 keydown 處理常式。這項屬性現在就值得瞭解,因為它精準定義了無障礙操作行為:工具列應只有一個 Tab 停駐點,而不是五個。這項原則早在該屬性出現前數十年便已存在。無論採用何種實作方式,ARIA Authoring Practices 都對此模式有所說明。
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>
錨點定位
使用原生 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;
}
捲動驅動動畫
讓動畫進度與捲動位置連動。不需 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 的元素定義初始樣式,無須 JavaScript,即可實現僅使用 CSS 的進場動畫。
.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 擷取工作流程
若要將設計檔案轉換為正式環境的程式碼,必須有系統地擷取設計 tokens,包括定義設計語言的色彩、字體排印、間距與效果。
匯出 Figma Variables
Figma 內建的 Variables 功能提供最簡潔的擷取方式:
匯出步驟:
1. 開啟 Figma 檔案→進入 Local Variables 面板,然後開啟集合
2. 以滑鼠右鍵按一下模式→「Export mode」(或以滑鼠右鍵按一下集合→「Export modes」——每個模式會產生一個 JSON 檔案)
3. 儲存匯出的檔案,例如 figma-variables.json
Figma 的內建匯出與匯入功能皆採用 DTCG 格式,使用 $value/$type 鍵,並以 / 串接群組名稱;匯入功能僅接受符合此結構的 tokens。
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 自訂屬性:
: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 的轉換
色彩擴充:
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 | 包含淺色與深色模式 |
| 字體排印 | 樣式匯出 | 字型、大小、字重、行高 |
| 間距 | Variables JSON | 記錄基準單位 |
| 圖示 | SVG | 外框樣式、單色 |
| 圖片 | PNG @2x/@3x 或 WebP | 經過壓縮 |
| 元件 | Figma 連結 | 供實作期間參考 |
品質關卡標準:
- [ ] 所有色彩皆定義為變數(未使用硬編碼的十六進位色碼)
- [ ] 字體排印採用已定義的文字樣式
- [ ] 間距遵循網格系統(以 8px 為基準)
- [ ] 已提供深色模式版本
- [ ] 已記錄互動狀態(懸停、啟用、停用)
- [ ] 已標註響應式中斷點
- [ ] 已註明無障礙需求(對比度)
開發人員會收到:
- Token 檔案(依平台提供 JSON/CSS/Swift)
- 含尺寸標示的元件規格
- 符合所需格式的素材匯出檔
- 互動說明文件(狀態、動畫)
- 無障礙標註
快速參考表
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 配色比例
視覺層級
- [ ] 能辨識出最重要的第 1 項元素
- [ ] 視線依照預期順序移動
- [ ] 每個區段僅有一個明確的 CTA
- [ ] 字級比例一致
間距
- [ ] 所有間距皆使用已定義的級距(不使用無依據的數值)
- [ ] 卡片/元件採用一致的內距
- [ ] 行動裝置上的間距舒適易讀
- [ ] 網格對齊方式一致(以 8px 為基準)
互動
- [ ] 使用者能否無須思考工具本身,便能達成目標?
- [ ] UI 是否能配合目前情境調整?
- [ ] 工具是否只在相關時機顯示?
- [ ] 重複使用時,是否會引導使用者學會更快速的方法?
AI 介面
- [ ] 每項事實陳述皆有可追溯的來源
- [ ] 串流過程會呈現處理階段,而不只是顯示載入圖示
- [ ] 錯誤狀態公開透明,而非加以隱藏
- [ ] 低可信度的輸出具有不同的視覺呈現
Dieter Rams 檢查
- [ ] 是否還能移除任何內容?
- [ ] 每個元素是否都有實際功能?
- [ ] 這項設計在 5 年後是否會顯得過時?
- [ ] 是否已設計所有狀態?
資源
書籍: - Sophie Lovell(Dieter Rams)著作《As Little Design as Possible》 - Robert Bringhurst 著作《The Elements of Typographic Style》
工具: - WebAIM 對比度檢查工具 - 字級比例產生器 - Figma Tokens Studio——設計 token 管理
設計系統: - Apple HIG - Material Design 3 - Radix UI - shadcn/ui
設計研究
深入剖析48款傑出產品,記錄值得借鏡的模式與原則。
開發者工具與AI
| 產品 | 關鍵貢獻 |
|---|---|
| Figma | 多人即時協作狀態、情境感知面板 |
| Warp | 區塊式終端機、CLI與GUI的橋接 |
| Framer | 視覺化響應式設計、屬性控制項 |
| Vercel | 卓越的深色模式、環境式狀態呈現 |
| Linear | 樂觀式UI(Optimistic UI)、鍵盤優先工作流程 |
| Raycast | 擴充功能系統、快速操作 |
| Stripe | 卓越的文件品質、API設計 |
| Perplexity | 引用優先的AI、串流階段 |
| Obsidian | 本機優先的可組合性、知識圖譜介面 |
Apple原生與創意工具
| 產品 | 關鍵貢獻 |
|---|---|
| Flighty | 15種智慧狀態、即時動態、資料視覺化 |
| Halide | 智慧啟用、手勢控制 |
| Bear | 排版優先、行內標籤 |
| Craft | 原生優先的跨平台體驗、巢狀頁面 |
| Things | 延後日期、快速輸入模式 |
| Darkroom | 沉浸式深色UI、相片優先編輯 |
| Procreate | 手勢優先的創意工具 |
| Overcast | 將無形的音訊工程化為介面設計 |
| Camo | 專業影片製作UI |
| Ivory | 時間軸工藝、趣味與精準兼具 |
| Anybox | 平台原生的透明度 |
| Drafts | 文字優先、清晰俐落的擷取體驗 |
| Notion Calendar | 精準的行事曆體驗、工作區整合 |
生產力、知識與金融
| 產品 | 關鍵貢獻 |
|---|---|
| Superhuman | 100ms法則、指令面板訓練、實作式新手引導 |
| Notion | 區塊系統、斜線指令 |
| Arc | 空間、分割檢視、指令列 |
| Todoist | 溫暖的極簡主義、極致克制 |
| Amie | 愉悅的生產力體驗、溫暖的極簡主義 |
| Loom | 友善而專業的非同步影片體驗 |
| Pitch | 大膽鮮明的簡報設計語彙 |
| Readwise Reader | 深度閱讀工具、宇宙風格品牌形象 |
| Copilot Money | 電影感十足的財務資料視覺化 |
| 1Password | 讓安全體驗流暢無礙 |
| Mercury | 電影感十足的精緻銀行體驗 |
消費、社交與信任
| 產品 | 關鍵貢獻 |
|---|---|
| Spotify | 色彩、情感與規模 |
| Duolingo | 將遊戲化化為設計語彙 |
| Signal | 以簡潔成就安全 |
| Airbnb | 大規模市集中的信任建立 |
| Bluesky | 演算法透明度 |
| Letterboxd | 將電影化為社交媒介 |
| Strava | 將GPS資料化為社交資本 |
| Apple Music | 編輯觀點、空間音訊 |
| Headspace | 以平靜作為介面策略 |
| Zomato | 以鮮明個性驅動的美食UX |
實體產品、遊戲與無障礙設計
| 產品 | 關鍵貢獻 |
|---|---|
| Balatro | 回饋迴圈、遊戲手感系統 |
| Rivian | 冒險攝影、氣勢恢宏的字體排印 |
| Teenage Engineering | 將限制化為美學識別 |
| OKO | 聲音與觸覺回饋的無障礙設計 |
| CARROT Weather | 以鮮明個性打造實用工具App的差異化 |
本指南在實踐中持續成長。設計原則歷久彌新,其應用方式則隨著技術與認知不斷演進。